Adorner的两种常用控制方式

2017-09-12 07:40:59来源:CSDN作者:zeng292390450人点击

分享

   在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有业务或者更高级的功能要做时,两者就有区别了。



最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台