wpf 使用 Drag Adorner 拖放
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18053832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Drag and Drop with Drag Adorner
提问by user2376998
i used a drag adorner to clone the image of my labels ( drag target ) but however now i couldn't drop my label into my textbox ,
我使用了一个拖动装饰器来克隆我的标签图像(拖动目标),但是现在我无法将我的标签放入我的文本框中,
this is the code i have used ( u might see theres previewdragover , i wrote e.Handled = true in previewdragover but doesn't help ) i have also set tbox.AllowDrop to true :
这是我使用的代码(你可能会看到有 previewdragover ,我在 previewdragover 中写了 e.Handled = true 但没有帮助)我也将 tbox.AllowDrop 设置为 true :
TextBox :
文本框 :
tbox.PreviewDrop += new DragEventHandler(tbox_PreviewDrop);
tbox.PreviewDragOver += new DragEventHandler(tbox_PreviewDragOver);
Handlers for textbox :
文本框的处理程序:
protected 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.Handled = true;
}
Label ( drag target ) :
标签(拖动目标):
Label lbl = new Label();
lbl.Content = s;
lbl.Width = Double.NaN;
lbl.Height = 40;
lbl.FontSize = 19;
lbl.MouseDown += new MouseButtonEventHandler(lbl_MouseDown);
lbl.MouseMove += new MouseEventHandler(lbl_MouseMove);
lbl.GiveFeedback += new GiveFeedbackEventHandler(lbl_GiveFeedback);
lbl.MouseUp += new MouseButtonEventHandler(lbl_MouseUp);
wrapPanel2.Children.Add(lbl);
Handlers for label :
标签处理程序:
private void lbl_MouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.OverrideCursor = Cursors.Arrow;
}
private void lbl_MouseDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(this);
}
private void lbl_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
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);
}
}
[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;
Now i can drag the labels with the labels following my cursor but i can't drop them in any textbox.
现在我可以拖动带有光标跟随标签的标签,但我不能将它们放在任何文本框中。
-----EDIT------------
- - -编辑 - - - - - -
I have put a dragenter for textbox like this :
我已经为这样的文本框放置了一个 Dragenter:
private void tbox_PreviewDragEnter(object sender, DragEventArgs e)
{
if (sender == e.Source)
{
e.Effects = DragDropEffects.None;
}
}
Still not working tho.
还是不行。
i'll add the DragAdorner.cs here that i've used ( i got it from some chinese web ) :
我将在这里添加我用过的 DragAdorner.cs(我从一些中文网站上得到的):
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;
回答by Job
The problem is that your drag adorner is always on top. When you try to drop your label it drops on the adorner instead of the underlying component.
问题是你的拖拽装饰器总是在上面。当您尝试删除标签时,它会落在装饰器上而不是底层组件上。
To avoid this add the following line to the constructor of the DragAdorner.
为避免这种情况,将以下行添加到 DragAdorner 的构造函数中。
IsHitTestVisible = false;
IsHitTestVisible = false;
回答by Sheridan
Your code is somewhat different to my working example, but I think that I can see your problem. In my code, I have a method called UpdateDragDropEffects. This method takes in an object of type DragEventArgsnamed eand updates the e.Effectsproperty dependent on the value of the e.AllowedEffectsproperty and also whether I have a valid ICommandinstance to call and whether the data is of the expected type, etc.
您的代码与我的工作示例有些不同,但我认为我可以看到您的问题。在我的代码中,我有一个名为UpdateDragDropEffects. 此方法接收一个DragEventArgs名为类型的对象,e并根据该e.Effects属性的值e.AllowedEffects以及我是否有一个有效的ICommand实例可以调用以及数据是否为预期类型等来更新该属性。
This method is called (and the DragEventArgsobject passed from) two typical drag and drop methods; DragTargetPreviewDrop(handles the PreviewDropevent) and AdornedUIElementPreviewDragOver(handles the PreviewDragOverevent). Setting the e.Effectsproperty of the DragEventArgsobject tells the system whether the current drag opearation is valid and should continue or not... not setting it, or setting it to DragDropEffects.Nonewill have the effect of not displaying any valid drop targets.
这个方法被调用(和DragEventArgs传递过来的对象)两个典型的拖放方法;DragTargetPreviewDrop(处理PreviewDrop事件)和AdornedUIElementPreviewDragOver(处理PreviewDragOver事件)。设置对象的e.Effects属性会DragEventArgs告诉系统当前拖动操作是否有效以及是否应该继续......不设置它,或者将它设置为DragDropEffects.None将不会显示任何有效的放置目标。
The Drag and Drop Overviewpage at MSDN has code examples that should also help you. The Enabling an Element to be a Drop Targetsection has example code that shows what I have described.
该拖放概述在MSDN页面有代码示例,也应该帮助你。该Enabling an Element to be a Drop Target部分有示例代码,显示了我所描述的内容。
You could also have other problems, but come back and update if this doesn't help you.
您还可能遇到其他问题,但如果这对您没有帮助,请返回并更新。
回答by Fou Lou
Initialize your Dragadorner with Point(-5,-5). (new DragAdorner(new Point(-5,-5));)
使用 Point(-5,-5) 初始化您的 Dragadorner。(new DragAdorner(new Point(-5,-5));)
The drop Event seems to be thrown on the Adorner. If you add a drop handler to the Adorner youll see that it gets called when you release the mouse.
drop 事件似乎是在 Adorner 上抛出的。如果您向 Adorner 添加一个放置处理程序,您会看到它在您松开鼠标时被调用。
It seems that the Mouse pointer is over the Adorner and it takes it as Target.
鼠标指针似乎在装饰器上方,并将其作为目标。
Setting the offset to a Point so that the Adorner is not under the Mousepointer corrects that behavior.
将偏移量设置为 Point 以便 Adorner 不在鼠标指针下方更正该行为。

