未触发WPF C#PreviewDrop/Drop事件(使用dragadorner)
我假设previewdrop/drop事件是在它检测到一个拖拽目标并将一个元素作为拖拽目标时触发的。在本例中,我的拖放目标是一个文本框,而我的拖动目标是一个标签。它们都是从DB动态创建的。我正在使用DragAdorner克隆我正在拖动的元素,在实现DragAdorner之前,我的DnD工作得很好,但是在我使用DragAdorner之后,它就不工作了。我注意到,当我尝试调试时,previewdrop事件没有触发 这是我的密码:未触发WPF C#PreviewDrop/Drop事件(使用dragadorner),c#,wpf,events,drag-and-drop,adorner,C#,Wpf,Events,Drag And Drop,Adorner,我假设previewdrop/drop事件是在它检测到一个拖拽目标并将一个元素作为拖拽目标时触发的。在本例中,我的拖放目标是一个文本框,而我的拖动目标是一个标签。它们都是从DB动态创建的。我正在使用DragAdorner克隆我正在拖动的元素,在实现DragAdorner之前,我的DnD工作得很好,但是在我使用DragAdorner之后,它就不工作了。我注意到,当我尝试调试时,previewdrop事件没有触发 这是我的密码: tbox.Drop += new DragEventHandler(
tbox.Drop += new DragEventHandler(tbox_PreviewDrop); // text box , Drop Target
tbox.DragOver += new DragEventHandler(tbox_DragOver);
Label lbl = new Label(); // Label , Drag Target
lbl.Content = s;
lbl.Width = Double.NaN;
lbl.Height = 40;
lbl.FontSize = 19;
lbl.PreviewMouseDown += new MouseButtonEventHandler(lbl_MouseDown);
lbl.PreviewMouseMove += new MouseEventHandler(lbl_MouseMove);
lbl.PreviewGiveFeedback += new GiveFeedbackEventHandler(lbl_GiveFeedback);
private void lbl_MouseDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(this);
// Mouse.OverrideCursor = Cursors.None;
}
private void lbl_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
// Mouse.OverrideCursor = Cursors.None;
var source = sender as UIElement;
Label lbl = sender as Label;
Point current = e.GetPosition(this);
Vector diff = startPoint - current;
if (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)
{
adorner = new DragAdorner(lbl, e.GetPosition(lbl));
AdornerLayer.GetAdornerLayer(lbl).Add(adorner);
var dragData = new DataObject(this);
DragDrop.DoDragDrop(source, dragData, DragDropEffects.Copy);
AdornerLayer.GetAdornerLayer(lbl).Remove(adorner);
}
startPoint = current;
}
}
private void lbl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (adorner != null)
{
Label lbl = sender as Label;
var pos = lbl.PointFromScreen(GetMousePosition());
adorner.UpdatePosition(pos);
e.Handled = true;
}
}
private void tbox_PreviewDrop(object sender, DragEventArgs e)
{
(sender as TextBox).Text = string.Empty; // Empty the textbox from previous answer.
(sender as TextBox).Background = Brushes.White;
e.Effects = DragDropEffects.Move;
e.Handled = true;
}
private void tbox_DragOver(object sender, DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.Move;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
public static Point GetMousePosition()
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return new Point(w32Mouse.X, w32Mouse.Y);
}
private Point startPoint;
private DragAdorner adorner;
和装饰器类文件:
public class DragAdorner : Adorner {
public DragAdorner(UIElement adornedElement, Point offset)
: base(adornedElement) {
this.offset = offset;
vbrush = new VisualBrush(AdornedElement);
//vbrush.Opacity = .7;
}
public void UpdatePosition(Point location) {
this.location = location;
this.InvalidateVisual();
}
protected override void OnRender(DrawingContext dc) {
var p = location;
p.Offset(-offset.X, -offset.Y);
dc.DrawRectangle(vbrush, null, new Rect(p, this.RenderSize));
}
private Brush vbrush;
private Point location;
private Point offset;
}
我看到了(第103页),但对我来说太复杂了,因为我是个新手
这是因为my GiveFeedBack事件与其他事件冲突?尝试设置标签的背景色,看看它是否能正常工作。由于您的
Dragader
始终位于光标下,因此它将是接收放置的对象。如果将ishitestvisible设置为false在装饰器的构造函数中,它应该修复此问题
即使您尚未在装饰器
上设置AllowDrop
,但由于它位于光标下方,它将拦截拖放尝试。但由于它不接受drop,它只会取消它
更新
另一个问题是,您正在将拖动操作中允许的效果设置为DragDropEffects.Copy
,但在DragOver
和Drop
处理程序中,您正在尝试执行DragDropEffects.Move
。这不起作用,因为这些操作不同。这些必须匹配。如果要在拖动时启用这两种操作,可以使用按位或:
DragDrop.DoDragDrop(source, dragData, DragDropEffects.Copy | DragDropEffects.Move);
更新2
如果要将字符串
以外的任何内容拖放到文本框
,则必须使用PreviewDrop
和PreviewDragOver
事件。否则,文本框的默认处理将忽略任何其他内容。所以看起来是这样的:
tbox.PreviewDrop += new DragEventHandler(tbox_PreviewDrop);
tbox.PreviewDragOver += new DragEventHandler(tbox_DragOver);
您好,我已将IshtestVisible设置为false。它还是不会掉下来。抱歉,我不太明白你关于拖放尝试和内容的第二句话基本上,WPF将在光标位置进行命中测试,并尝试拖放到最上面的元素。如果该元素不接受drops,则该操作将被取消。这就是为什么在你的装饰器
上禁用命中测试是很重要的(装饰器
总是在顶部)。我已经禁用了命中测试,不起作用,还有其他问题吗?嗨,我尝试了一起复制和移动,也不起作用。。这是因为装饰程序无法拖动到文本框中吗?好吧,使用PreviewDrag
和PreviewDrop
,您可以操纵数据,以便将所需内容放到文本框中。但是如果拖动字符串,则文本框可以自己处理它。