ToB企服应用市场:ToB评测及商务社交产业平台

标题: WPF-利用装饰器实现空间的自由拖动 [打印本页]

作者: 九天猎人    时间: 2023-9-1 09:51
标题: WPF-利用装饰器实现空间的自由拖动
  在项目中经常会遇到类似如下要求的需求,创建允许自由拖动的控件,这样的需求可以使用WPF的装饰器Adorner来实现。

 
一、什么是装饰器?

装饰器是一种特殊类型的FrameworkElement,装饰器始终呈现在被装饰元素的顶部,用于向用户提供可视化提示。装饰器可以在不改变原有控件结构的基础上,将功能点增加到元素中或元素上提供视觉效果等,如WPF的光标效果,焦点效果等都是通过装饰器来实现的。装饰器是一个始终位于装饰元素或装饰元素集合顶部的呈现图层,其呈现独立与它所绑定的UIElement,WPF中的装饰器是在一个单独的曾AnornerLayer上进行绘制的,该层位于普通控件元素之上,而且允许多个AdornerLayer进行叠加,当加入AdornerLayer层后,Adorner会默认使用其所装饰元素的左上角作为原点进行定位。
二、装饰器的使用场景

 三、如何创建自定义的装饰器?

 四、给控件使用自定义的Adorner

  1. AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl);
  2. if (adornerLayer != null)
  3. {
  4.     Adorner[] adorners = adornerLayer.GetAdorners(userControl);
  5.     if (adorners == null || adorners.Count() == 0)
  6.     {
  7.         adornerLayer.Add(new ThumbBorderAdorner(userControl)
  8.         {
  9.             DragCompletedAction = ThumbBorderAdornerDragCompletedActionFunc
  10.         });
  11.     }
  12. }
复制代码
 
  1. AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(userControl);
  2. if (adornerLayer != null)
  3. {
  4.     Adorner[] adorners = adornerLayer.GetAdorners(userControl);
  5.     if (adorners != null && adorners.Count() > 0)
  6.         adornerLayer.Remove(adorners[0]);
  7. }
复制代码
 
五、处理拖拽Thumb时,导致控件范围超出父级容器的情况

  1. private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
  2. {
  3.     int tempMargin = 1;  //MarkRectUserControl控件始终在父级容器的1个像素以内
  4.     double left = Canvas.GetLeft(this);
  5.     if (left < tempMargin)
  6.     {
  7.         left = tempMargin;
  8.         Canvas.SetLeft(this, left);
  9.     }
  10.     double top = Canvas.GetTop(this);
  11.     if (top < tempMargin)
  12.     {
  13.         top = tempMargin;
  14.         Canvas.SetTop(this, top);
  15.     }
  16.     if (left + this.ActualWidth > canvasParent.ActualWidth - tempMargin)
  17.         this.Width = canvasParent.ActualWidth - tempMargin - left;
  18.     if (top + this.ActualHeight > canvasParent.ActualHeight - tempMargin)
  19.         this.Height = canvasParent.ActualHeight - tempMargin - top;
  20. }
复制代码
 
六、测试使用

 
  1. <UserControl x:Class="BlogDemo.Views.AdornerTestUserControl"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.              xmlns:local="clr-namespace:BlogDemo.Views"
  7.              mc:Ignorable="d"
  8.              Background="White"
  9.              d:DesignHeight="450" d:DesignWidth="800"
  10.              FontSize="20"
  11.              Foreground="Blue"
  12.              Loaded="UserControl_Loaded"
  13.              >
  14.     <Grid>
  15.         <Grid.RowDefinitions>
  16.             <RowDefinition Height="Auto"/>
  17.             <RowDefinition Height="*"/>
  18.         </Grid.RowDefinitions>
  19.         
  20.         <TextBlock Text="请拖拽Thumb控件来改变,控件大小。" HorizontalAlignment="Center" Margin="10"/>
  21.         <Canvas x:Name="Canvas_Main" Grid.Row="1">
  22.             <Border x:Name="Border_Text" Canvas.Left="200" Canvas.Top="100" Width="200" Height="100" BorderThickness="2" BorderBrush="Green" SizeChanged="Border_Text_SizeChanged"/>
  23.         </Canvas>
  24.     </Grid>
  25. </UserControl>
复制代码
  1. /// <summary>
  2. /// AdornerTestUserControl.xaml 的交互逻辑
  3. /// </summary>
  4. public partial class AdornerTestUserControl : UserControl
  5. {
  6.     public AdornerTestUserControl()
  7.     {
  8.         InitializeComponent();
  9.     }
  10.     private void UserControl_Loaded(object sender, RoutedEventArgs e)
  11.     {
  12.         AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(Border_Text);
  13.         if (adornerLayer != null)
  14.         {
  15.             Adorner[] adorners = adornerLayer.GetAdorners(Border_Text);
  16.             if (adorners == null || adorners.Count() == 0)
  17.             {
  18.                 adornerLayer.Add(new ThumbBorderAdorner(Border_Text));
  19.             }
  20.         }
  21.     }
  22.     private void Border_Text_SizeChanged(object sender, SizeChangedEventArgs e)
  23.     {
  24.         int tempMargin = 100;
  25.         double left = Canvas.GetLeft(Border_Text);
  26.         if (left < tempMargin)
  27.         {
  28.             left = tempMargin;
  29.             Canvas.SetLeft(Border_Text, left);
  30.         }
  31.         double top = Canvas.GetTop(Border_Text);
  32.         if (top < tempMargin)
  33.         {
  34.             top = tempMargin;
  35.             Canvas.SetTop(Border_Text, top);
  36.         }
  37.         if (Border_Text.ActualWidth < tempMargin)
  38.             Border_Text.Width = tempMargin;
  39.         if (Border_Text.ActualHeight < tempMargin)
  40.             Border_Text.Height = tempMargin;
  41.         if (left + Border_Text.ActualWidth > Canvas_Main.ActualWidth - tempMargin)
  42.             Border_Text.Width = Canvas_Main.ActualWidth - tempMargin - left;
  43.         if (top + Border_Text.ActualHeight > Canvas_Main.ActualHeight - tempMargin)
  44.             Border_Text.Height = Canvas_Main.ActualHeight - tempMargin - top;
  45.     }
  46. }
复制代码
 
 
源码地址:https://gitee.com/LiuShuiRuoBing/code_blog
 
 
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4