WPF Adorner+附加属性 实现控件友好提示

标题太空泛,直接上图

 WPF Adorner+附加属性 实现控件友好提示

无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做?

这里介绍一种稍微简单一些的方法,利用附加属性和Adorner来完成。

 

例如WPF自带的控件上要加这样的效果,首先继承自原控件然后重写是可以的,但是控件类型太多,重写不过来。这个时候我们唯一能添加的只有附加属性了。

利用附加属性的属性变更事件PropertyChangedCallBack,我们可以获取到宿主对象即Button,然后就可以往Button上加入我们自定义的Adorner了。再添加一个附加属性控制Adorner的显示/隐藏,那么就很完美了,这样每个控件只用设置两个附加属性就能拥有上面的效果。下面是核心代码,

附加属性

public class AdornerHelper

    {

        #region 是否有Adorner

        public static bool GetHasAdorner(DependencyObject obj)

        {

            return (bool)obj.GetValue(HasAdornerProperty);

        }



        public static void SetHasAdorner(DependencyObject obj, bool value)

        {

            obj.SetValue(HasAdornerProperty, value);

        }



        // Using a DependencyProperty as the backing store for HasAdorner.  This enables animation, styling, binding, etc...

        public static readonly DependencyProperty HasAdornerProperty =

            DependencyProperty.RegisterAttached("HasAdorner", typeof(bool), typeof(AdornerHelper), new PropertyMetadata(false, PropertyChangedCallBack));



        private static void PropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            if ((bool)e.NewValue)

            {

                var element = d as Visual;



                if (element != null)

                {

                    var adornerLayer = AdornerLayer.GetAdornerLayer(element);



                    if (adornerLayer!=null)

                    {

                        adornerLayer.Add(new NotifyAdorner(element as UIElement)); 

                    }

                }

            }

        } 

        #endregion



        #region 是否显示Adorner





        public static bool GetIsShowAdorner(DependencyObject obj)

        {

            return (bool)obj.GetValue(IsShowAdornerProperty);

        }



        public static void SetIsShowAdorner(DependencyObject obj, bool value)

        {

            obj.SetValue(IsShowAdornerProperty, value);

        }



        // Using a DependencyProperty as the backing store for IsShowAdorner.  This enables animation, styling, binding, etc...

        public static readonly DependencyProperty IsShowAdornerProperty =

            DependencyProperty.RegisterAttached("IsShowAdorner", typeof(bool), typeof(AdornerHelper), new PropertyMetadata(false,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() as NotifyAdorner;



                        if (adorner == null)

                        {

                            return;

                        }



                        if ((bool)e.NewValue)

                        {

                            adorner.ShowAdorner();

                        }

                        else

                        {

                            adorner.HideAdorner();

                        }

                    } 

                }

            }

        }



        #endregion

    }

然后是我们自定义的Adorner效果

public class NotifyAdorner : Adorner

    {

        private VisualCollection _visuals;

        private Canvas _grid;

        private Image _image;



        public NotifyAdorner(UIElement adornedElement)

            : base(adornedElement)

        {

            _visuals = new VisualCollection(this);

            _image=new Image()

            {

                Source = new BitmapImage(new Uri("Notify.png",UriKind.RelativeOrAbsolute)),

                Width = 25,

                Height = 25

            };



            _grid = new Canvas();

            _grid.Children.Add(_image);



            _visuals.Add(_grid);

        }



        public void ShowAdorner()

        {

            _image.Visibility = Visibility.Visible;

        }



        public void HideAdorner()

        {

            _image.Visibility = Visibility.Collapsed;

        }



        protected override int VisualChildrenCount

        {

            get

            {

                return _visuals.Count;

            }

        }



        protected override Visual GetVisualChild(int index)

        {

            return _visuals[index];

        }



        protected override Size MeasureOverride(Size constraint)

        {

            return base.MeasureOverride(constraint);

        }



        protected override Size ArrangeOverride(Size finalSize)

        {

            _grid.Arrange(new Rect(finalSize));



            _image.Margin=new Thickness(finalSize.Width-12.5,-12.5,0,0);



            return base.ArrangeOverride(finalSize);

        }





    }


这里是源码http://files.cnblogs.com/HelloMyWorld/AdornerSample.rar

大家看代码就能懂了

你可能感兴趣的:(WPF)