关于控件的平移,我们之前学习转换时,曾经对TranslateTransform进行了讲解和示例。在那个示例中,我们只需要设置TranslateTransform的X属性和Y属性,使可以移动一个控件的位置。在学习了行为之后,我们肯定不希望一遍又一遍地去实现控件的移动效果,如果将移动效果做成一个行为,那么,任何一个控件,只要想拥有移动效果,直接调用行为即可,岂不快哉。
实现思路:
1、TranslateTransform平移对象最终赋值给RenderTransform属性,而RenderTransform位于UIElement基类中,所以,行为的泛型T参数应设置为UIElement。
2、TranslateTransform的X和Y是当前控件平移的位置坐标,这个坐标相对于当前控件的父控件而言的,所以在实现行为时,要拿到这个父控件。
3、我们采用鼠标去拖拽一个控件进行平移,所以要获取鼠标按下时的位置和移动过程中的位置,从而才知道TranslateTransform要平移到什么位置。
4、如果当前被移动的控件没有TranslateTransform,我们需要先给它实例化一个TranslateTransform对象。
根据上面的思路,我们来实现这个移动行为。
public class DragBehavior : Behavior<FrameworkElement>
{
protected bool isDragging = false;
private Point startPosition;
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseDown += AssociatedObject_MouseDown;
AssociatedObject.MouseMove += AssociatedObject_MouseMove;
AssociatedObject.MouseUp += AssociatedObject_MouseUp;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseDown -= AssociatedObject_MouseDown;
AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
AssociatedObject.MouseUp -= AssociatedObject_MouseUp;
}
private void AssociatedObject_MouseDown(object sender,
System.Windows.Input.MouseButtonEventArgs e)
{
isDragging = true;
var parent = AssociatedObject.Parent as FrameworkElement;
var clickPosition = e.GetPosition(parent);
//首次按下时,判断RenderTransform的类型是否为TranslateTransform
if (!(AssociatedObject.RenderTransform is TranslateTransform))
{
AssociatedObject.RenderTransform = new TranslateTransform();
}
var transform = AssociatedObject.RenderTransform as TranslateTransform;
startPosition.X = clickPosition.X - transform.X;
startPosition.Y = clickPosition.Y - transform.Y;
AssociatedObject.CaptureMouse();//强制鼠标捕捉
}
private void AssociatedObject_MouseMove(object sender,
System.Windows.Input.MouseEventArgs e)
{
if (isDragging)
{
var parent = AssociatedObject.Parent as FrameworkElement;
Point currentPosition = e.GetPosition(parent);
var transform = AssociatedObject.RenderTransform as TranslateTransform;
transform.X = currentPosition.X - startPosition.X;
transform.Y = currentPosition.Y - startPosition.Y;
}
}
private void AssociatedObject_MouseUp(object sender,
System.Windows.Input.MouseButtonEventArgs e)
{
isDragging = false;
AssociatedObject.ReleaseMouseCapture();//释放鼠标捕捉
}
}
下一步,我们在需要移动的控件上引用这个行为。
<Window x:Class="HelloWorld.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:HelloWorld"
xmlns:controls="clr-namespace:HelloWorld.Controls"
xmlns:helper="clr-namespace:HelloWorld.MVVM"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:behavior="clr-namespace:HelloWorld.Behaviors"
mc:Ignorable="d" Background="DarkCyan"
Title="WPF中文网 - 行为 - www.wpfsoft.com" Height="350" Width="500">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Canvas>
<Border Width="50" Height="50" CornerRadius="50"
Background="LightGoldenrodYellow"
Canvas.Left="228" Canvas.Top="20">
<i:Interaction.Behaviors>
<behavior:ShadowBehavior/>
<behavior:DragBehavior/>
</i:Interaction.Behaviors>
</Border>
<TextBlock Text="WPF中文网"
Foreground="White"
FontSize="60"
Canvas.Left="92"
Canvas.Top="75">
<i:Interaction.Behaviors>
<behavior:ShadowBehavior/>
<behavior:DragBehavior/>
</i:Interaction.Behaviors>
</TextBlock>
<TextBlock Text="Behavior行为之阴影效果"
Foreground="White"
FontSize="40"
Canvas.Left="21"
Canvas.Top="182">
<i:Interaction.Behaviors>
<behavior:ShadowBehavior/>
<behavior:DragBehavior/>
</i:Interaction.Behaviors>
</TextBlock>
<Button Content="退出" Width="80" Height="30"
FontSize="14"
Canvas.Left="375" Canvas.Top="265">
<i:Interaction.Behaviors>
<behavior:ShadowBehavior/>
<behavior:DragBehavior/>
</i:Interaction.Behaviors>
</Button>
</Canvas>
</Window>
这是鼠标移动之前的效果。
这是鼠标随意移动之后的效果。
当前课程源码下载:(注明:本站所有源代码请按标题搜索)
文件名:108-《行为之控件移动效果》-源代码
——重庆教主 2023年11月21日
链接:https://pan.baidu.com/s/1yu-q4tUtl0poLVgmcMfgBA
提取码:wpff