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

简介: 原文:WPF Adorner+附加属性 实现控件友好提示标题太空泛,直接上图   无论是在验证啊,还是提示方面等一些右上角的角标之类的效果,我们会怎么做? 这里介绍一种稍微简单一些的方法,利用附加属性和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

大家看代码就能懂了

目录
相关文章
|
7月前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
392 0
|
7月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
144 1
|
4月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
4月前
|
C# 开发者 Windows
一款基于Fluent设计风格、现代化的WPF UI控件库
一款基于Fluent设计风格、现代化的WPF UI控件库
100 1
|
4月前
|
C# Windows
WPF中如何使用HandyCotrol控件库
WPF中如何使用HandyCotrol控件库
198 1
|
4月前
|
C# 开发者 Windows
全面指南:WPF无障碍设计从入门到精通——让每一个用户都能无障碍地享受你的应用,从自动化属性到焦点导航的最佳实践
【8月更文挑战第31天】为了确保Windows Presentation Foundation (WPF) 应用程序对所有用户都具备无障碍性,开发者需关注无障碍设计原则。这不仅是法律要求,更是社会责任,旨在让技术更人性化,惠及包括视障、听障及行动受限等用户群体。
85 0
|
4月前
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
127 0
|
4月前
|
C# UED 定位技术
WPF控件大全:初学者必读,掌握控件使用技巧,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,控件是实现用户界面交互的关键元素。WPF提供了丰富的控件库,包括基础控件(如`Button`、`TextBox`)、布局控件(如`StackPanel`、`Grid`)、数据绑定控件(如`ListBox`、`DataGrid`)等。本文将介绍这些控件的基本分类及使用技巧,并通过示例代码展示如何在项目中应用。合理选择控件并利用布局控件和数据绑定功能,可以提升用户体验和程序性能。
71 0
|
4月前
|
开发框架 前端开发 JavaScript
WPF应用开发之控件动态内容展示
WPF应用开发之控件动态内容展示
|
4月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件