WPF

您所在的位置:网站首页 MVVM能不能托控件生成 WPF

WPF

2024-07-15 08:24| 来源: 网络整理| 查看: 265

  在项目中经常会遇到类似如下要求的需求,创建允许自由拖动的控件,这样的需求可以使用WPF的装饰器Adorner来实现。

 

一、什么是装饰器? 装饰器是一种特殊类型的FrameworkElement,装饰器始终呈现在被装饰元素的顶部,用于向用户提供可视化提示。装饰器可以在不改变原有控件结构的基础上,将功能点增加到元素中或元素上提供视觉效果等,如WPF的光标效果,焦点效果等都是通过装饰器来实现的。 装饰器是一个始终位于装饰元素或装饰元素集合顶部的呈现图层,其呈现独立与它所绑定的UIElement,WPF中的装饰器是在一个单独的曾AnornerLayer上进行绘制的,该层位于普通控件元素之上,而且允许多个AdornerLayer进行叠加,当加入AdornerLayer层后,Adorner会默认使用其所装饰元素的左上角作为原点进行定位。 Adorner 是一个抽象类,所有装饰器的实现都需要继承此类,比如ThumbBorderAdorner AdornerLayer 一个类,表示一个或多个装饰元素的装饰器呈现层 利用AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl)函数,来获取指定控件是否有装饰器布局层 利用Adorner[] adorners = adornerLayer.GetAdorners(userControl);,来查看当前控件的装饰器个数 AdornerDecorator 一个类,为可视化树中的子元素提供AdornerLayer 0 二、装饰器的使用场景 为现有的元素添加额外的装饰,如为Border添加8个装饰矩形   三、如何创建自定义的装饰器? 创建一个类,继承自Adorner类 重写此类中需要的函数 OnRender(DrawingContext drawingContext) 在派生类中重写,参与由布局系统控制的呈现操作,调用此方法时,不直接使用此元素的呈现指令,而是将其保留供布局和绘制在以后异步使用,可以使用drawingContext 来绘制各种形状以及图形。 ArrangeOverride() 为FrameworkElement派生类定位子元素并确定大小,在其中调用Arrange()函数,来定位子元素 GetVisualChild() //获取第几个Thumb控件,在构造时使用 简单的装饰可以重写OnRender()函数,在其中绘制所需要的装饰,参照BorderAdorner 复杂一些的如需要可以定义VisualCollection的集合来存放装饰器,重写ArrangeOverride和GetVisualChild函数来实现,参照ThumbBorderAdorner   四、给控件使用自定义的Adorner 添加Adorner AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl); if (adornerLayer != null) { Adorner[] adorners = adornerLayer.GetAdorners(userControl); if (adorners == null || adorners.Count() == 0) { adornerLayer.Add(new ThumbBorderAdorner(userControl) { DragCompletedAction = ThumbBorderAdornerDragCompletedActionFunc }); } }

 

移除 Adorner AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl); if (adornerLayer != null) { Adorner[] adorners = adornerLayer.GetAdorners(userControl); if (adorners != null && adorners.Count() > 0) adornerLayer.Remove(adorners[0]); }

 

五、处理拖拽Thumb时,导致控件范围超出父级容器的情况 即在添加装饰器的控件中添加UserControl_SizeChanged()来处理控件大小和和未知变化 private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) { int tempMargin = 1; //MarkRectUserControl控件始终在父级容器的1个像素以内 double left = Canvas.GetLeft(this); if (left canvasParent.ActualHeight - tempMargin) this.Height = canvasParent.ActualHeight - tempMargin - top; }

 

六、测试使用

 

/// /// AdornerTestUserControl.xaml 的交互逻辑 /// public partial class AdornerTestUserControl : UserControl { public AdornerTestUserControl() { InitializeComponent(); } private void UserControl_Loaded(object sender, RoutedEventArgs e) { AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(Border_Text); if (adornerLayer != null) { Adorner[] adorners = adornerLayer.GetAdorners(Border_Text); if (adorners == null || adorners.Count() == 0) { adornerLayer.Add(new ThumbBorderAdorner(Border_Text)); } } } private void Border_Text_SizeChanged(object sender, SizeChangedEventArgs e) { int tempMargin = 100; double left = Canvas.GetLeft(Border_Text); if (left


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3