lor*_*ris 14 c# wpf user-controls canvas drag
我正在编写我的第一个WPF应用程序.我有一个Canvas,用户可以在其中添加包含表单的UserControl子类.用户应该能够在Canvas周围拖动这些UserControl.使用WPF执行此操作的最佳做法是什么?谢谢.
Cor*_*old 40
这是在silverlight中完成的,而不是在WPF中完成的,但它应该工作相同.
在控件上创建两个私有属性:
protected bool isDragging;
private Point clickPosition;
Run Code Online (Sandbox Code Playgroud)
然后在控件的构造函数中附加一些事件处理程序:
this.MouseLeftButtonDown += new MouseButtonEventHandler(Control_MouseLeftButtonDown);
this.MouseLeftButtonUp += new MouseButtonEventHandler(Control_MouseLeftButtonUp);
this.MouseMove += new MouseEventHandler(Control_MouseMove);
Run Code Online (Sandbox Code Playgroud)
现在创建这些方法:
private void Control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
isDragging = true;
var draggableControl = sender as UserControl;
clickPosition = e.GetPosition(this);
draggableControl.CaptureMouse();
}
private void Control_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
isDragging = false;
var draggable = sender as UserControl;
draggable.ReleaseMouseCapture();
}
private void Control_MouseMove(object sender, MouseEventArgs e)
{
var draggableControl = sender as UserControl;
if (isDragging && draggableControl != null)
{
Point currentPosition = e.GetPosition(this.Parent as UIElement);
var transform = draggableControl.RenderTransform as TranslateTransform;
if (transform == null)
{
transform = new TranslateTransform();
draggableControl.RenderTransform = transform;
}
transform.X = currentPosition.X - clickPosition.X;
transform.Y = currentPosition.Y - clickPosition.Y;
}
}
Run Code Online (Sandbox Code Playgroud)
这里需要注意的几点:
1.这不一定要在画布上.它也可以位于堆叠面板或网格中.
2.这使整个控件可拖动,这意味着如果您单击控件中的任意位置并拖动它将拖动整个控件.不确定那是不是你想要的.
编辑 -
扩展你问题中的一些细节:我实现这个的最好方法是创建一个继承自UserControl的类,也许叫做使用此代码构建的DraggableControl,然后所有可拖动的控件都应该扩展DraggableControl.
编辑2 - 在此控件中有数据网格时,存在一个小问题.如果对数据网格中的列进行排序,则MouseLeftButtonUp事件永远不会触发.我已更新代码,以便isDragging受到保护.我发现最好的解决方案是将此匿名方法绑定到datagrid的LostMouseCapture事件:
this.MyDataGrid.LostMouseCapture += (sender, e) => { this.isDragging = false; };
Run Code Online (Sandbox Code Playgroud)
科里的回答大部分是正确的,但它缺少一个关键要素:对上次转换的记忆。否则,当您移动一个项目时,松开鼠标按钮,然后再次单击该项目,变换将重置为(0,0)并且控件跳回其原点。
这是一个对我有用的稍微修改过的版本:
public partial class DragItem : UserControl
{
protected Boolean isDragging;
private Point mousePosition;
private Double prevX, prevY;
public DragItem()
{
InitializeComponent();
}
private void UserControl_MouseLeftButtonDown(Object sender, MouseButtonEventArgs e)
{
isDragging = true;
var draggableControl = (sender as UserControl);
mousePosition = e.GetPosition(Parent as UIElement);
draggableControl.CaptureMouse();
}
private void UserControl_MouseLeftButtonUp(Object sender, MouseButtonEventArgs e)
{
isDragging = false;
var draggable = (sender as UserControl);
var transform = (draggable.RenderTransform as TranslateTransform);
if (transform != null)
{
prevX = transform.X;
prevY = transform.Y;
}
draggable.ReleaseMouseCapture();
}
private void UserControl_MouseMove(Object sender, MouseEventArgs e)
{
var draggableControl = (sender as UserControl);
if (isDragging && draggableControl != null)
{
var currentPosition = e.GetPosition(Parent as UIElement);
var transform = (draggableControl.RenderTransform as TranslateTransform);
if (transform == null)
{
transform = new TranslateTransform();
draggableControl.RenderTransform = transform;
}
transform.X = (currentPosition.X - mousePosition.X);
transform.Y = (currentPosition.Y - mousePosition.Y);
if (prevX > 0)
{
transform.X += prevX;
transform.Y += prevY;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
关键是存储之前的 X 和 Y 偏移量,然后使用它们来增加当前移动的偏移量,以达到正确的聚合偏移量。
| 归档时间: |
|
| 查看次数: |
22611 次 |
| 最近记录: |