Adorner的两种常用控制方式

本文介绍WPF中Adorner的两种控制方法:使用附加属性控制和通过Behavior模式控制。这两种方法分别适用于不同场景,前者适用于简单的提示功能,后者则适合更复杂的业务逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   在WPF界面设计中,Adorner可以为好的界面锦上添花,使用它的方式很多,现在WPF的设计模式一般是MVVM,为了满足需求,可以通过以下两种方式控制Adorner。

   1.使用附加属性控制Adorner:

    添加一个类,其中包含一个依赖属性,以及一个设置Adorner的方法,依赖属性代码如下:

    

 public static readonly DependencyProperty IsShowAdornerProperty =
            DependencyProperty.RegisterAttached("IsShowAdorner", typeof(bool), typeof(AdornerHelper), new PropertyMetadata(true,IsShowChangedCallBack));

        private static void IsShowChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as UIElement;
            if (element != null)
            {
                var adornerLayer = AdornerLayer.GetAdornerLayer(element);
                if (adornerLayer!=null)
                {
                    var adorners = adornerLayer.GetAdorners(element);
                    if (adorners != null && adorners.Count() != 0)
                    {
                        var adorner = adorners.FirstOrDefault();

                        if (adorner == null)
                        {
                            return;
                        }
                        adorner.Visibility = (bool) e.NewValue ? Visibility.Visible : Visibility.Hidden;
                    } 
                }
            }
        }

   这个属性控制Adorner的显示状态。外部设置方法代码:

 public static void SetAdorner(DependencyObject obj, Adorner adorner)
        {
            var element = obj as Visual;
            if (element!=null)
            {
                var adornerLayer = AdornerLayer.GetAdornerLayer(element);
                if (adornerLayer==null) throw new NullReferenceException($"在{obj}没发现AdornerLayer");
                adornerLayer.Add(adorner);               
            }
        }

  在代码中给元素设置Adorner,Adorner的实现方式自选。代码中应用:

  

<Button x:Name="Button" Width="50" Height="50" Margin="234,67,234.4,203.8" adornerSample:AdornerHelper.IsShowAdorner="True"></Button>

后台代码:

AdornerHelper.SetAdorner(Button,new YouAdorner());
在MVVM模式中可以绑定控制Adorner的显示状况。

  2.通过Behavior模式控制元素的Adorner

  此方式的Adorner采用Xaml的形式定义Adorner的外观,所以需要多设置一个依赖属性AdornerTemplate。
  继承实现一个基本的Adorner类,需要修该一些默认的方法,构造函数传入一个元素作为Adorner唯一的子元素。代码:

  

public  class BaseAdorner:Adorner
    {

        FrameworkElement _frameworkElementAdorner;

        public BaseAdorner(UIElement adornedElement,FrameworkElement framework):base(adornedElement)
        {
            _frameworkElementAdorner = framework;
            AddLogicalChild(_frameworkElementAdorner);
            AddVisualChild(_frameworkElementAdorner);
        }
        protected override Visual GetVisualChild(int index)
        {
            return _frameworkElementAdorner;
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return 1;
            }
        }
        protected override Size ArrangeOverride(Size finalSize)
        {
            _frameworkElementAdorner.Arrange(new Rect(new Point(0, 0), finalSize));
            return finalSize;
        }
        protected override Size MeasureOverride(Size constraint)
        {
            _frameworkElementAdorner.Width = constraint.Width;
            _frameworkElementAdorner.Height = constraint.Height;

            return constraint;
        }
    }

  实现自己的Behavior,代码如下:

 public  class BaseAdornerBehavior: Behavior<DependencyObject>
    { 
        private BaseAdorner _adorner;
        private ContentControl _adornerContentControl;

        private readonly Func<bool> _adornerTemplateFactory;

        #region 依赖属性
      
        public static readonly DependencyProperty AdornerTemplateProperty = DependencyProperty.Register(
            "AdornerTemplate", typeof(DataTemplate), typeof(BaseAdornerBehavior), new PropertyMetadata(new PropertyChangedCallback(
                delegate(DependencyObject o, DependencyPropertyChangedEventArgs args)
                {
                    if (null != ((BaseAdornerBehavior)o)._adornerContentControl)
                        ((BaseAdornerBehavior)o)._adornerContentControl.ContentTemplate = (DataTemplate)args.NewValue;
                })));
        /// <summary>
        /// adorner的样式
        /// </summary>
        public DataTemplate AdornerTemplate
        {
            get { return (DataTemplate) GetValue(AdornerTemplateProperty); }
            set { SetValue(AdornerTemplateProperty, value); }
        }

        public static readonly DependencyProperty AdornerVisibleProperty = DependencyProperty.Register(
            "AdornerVisible", typeof(Visibility), typeof(BaseAdornerBehavior), new PropertyMetadata((object)Visibility.Hidden,new PropertyChangedCallback((
                (o, args) =>
                {
                    if (null != ((BaseAdornerBehavior)o)._adornerContentControl)
                        ((BaseAdornerBehavior)o)._adornerContentControl.Visibility = (Visibility)args.NewValue;
                }))));
        /// <summary>
        /// adorner可见性
        /// </summary>
        public Visibility AdornerVisible
        {
            get { return (Visibility) GetValue(AdornerVisibleProperty); }
            set { SetValue(AdornerVisibleProperty, value); }
        }

        #endregion

        #region 命令

        public ICommand ShowAdornerCommand { get; private set; }
        public ICommand HideAdornerCommand { get; private set; }
        #endregion
        public BaseAdornerBehavior()
        {
            _adornerTemplateFactory = () =>
            {
                if (AdornerTemplate != null)
                {
                    //获取元素的adornerlayer
                    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(AssociatedObject as UIElement);
                    if (null == adornerLayer)
                        throw new NullReferenceException(string.Format("No adorner found in attached object: {0}",
                            AssociatedObject));
                    //
                    _adornerContentControl = new ContentControl();
                    //添加adorner
                    adornerLayer.Add(_adorner = new BaseAdorner(AssociatedObject as UIElement, _adornerContentControl));
                    //加载样式
                    _adornerContentControl.Content = AdornerTemplate.LoadContent();
                    _adornerContentControl.Visibility = Visibility.Visible;

                    //绑定margin属性到adorner
                    Binding bindingMargin = new Binding("AdornerMargin");
                    bindingMargin.Source = this;
                    BindingOperations.SetBinding(_adorner, ContentControl.MarginProperty, bindingMargin);
                }
                return true;
            };

            //初始化命令
            ShowAdornerCommand=new ActionCommand(() =>
            {
                var dtContext = (this.AssociatedObject as FrameworkElement).DataContext;
                if (null == _adornerContentControl.DataContext)
                    _adornerContentControl.DataContext = dtContext;

                _adornerContentControl.Visibility = Visibility.Visible;
            });
            HideAdornerCommand=new ActionCommand((() =>
            {
                _adornerContentControl.Visibility=Visibility.Hidden;
                //if (_adornerContentControl.IsMouseOver)
                //{
                //    _adornerContentControl.MouseLeave -= (s, e) =>
                //    {
                //        _adornerContentControl.Visibility = AdornerVisible;
                //    };
                //    _adornerContentControl.MouseLeave += (s, e) =>
                //    {
                //        _adornerContentControl.Visibility = AdornerVisible;
                //    };
                //}
            }));
        }

        #region override

        protected override void OnAttached()
        {
            base.OnAttached();
            _adornerTemplateFactory();
        }

        #endregion
    }


 代码没什么好说的,自己理解。

 代码中的应用,哦,忘了说这个需要Blend的sdk,在Nuget中获取,搜索Blend就能找到,代码:

 

<Custom:Interaction.Behaviors>
                    <adornerBehavior:BaseAdornerBehavior AdornerTemplate="{StaticResource AdornerDataTemplate}">
                        <Custom:Interaction.Triggers>
                           
                                <Custom:EventTrigger SourceName="arc" EventName="MouseEnter">
                                    <Custom:InvokeCommandAction CommandName="ShowAdornerCommand"/>
                                </Custom:EventTrigger>
                                <Custom:EventTrigger SourceName="arc" EventName="MouseLeave">
                                    <Custom:InvokeCommandAction CommandName="HideAdornerCommand"/>
                                </Custom:EventTrigger>
                         
                        </Custom:Interaction.Triggers>
                    </adornerBehavior:BaseAdornerBehavior>
</Custom:Interaction.Behaviors>

需要添加Adorner的元素添加以上代码,上面的Adorner的模板是我自己定义的。代码就不贴了。


总结一下:两种方式难度都不大,但是第二种方式更现代一点。当Adorner仅仅做到提示,没有复杂的处理时,当Adorner有业务或者更高级的功能要做时,两者就有区别了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值