gpt4 book ai didi

c# - WPF 使用鼠标和触摸与 Adorner 一起拖放

转载 作者:行者123 更新时间:2023-11-30 16:06:11 33 4
gpt4 key购买 nike

我希望这是一个很好的问题,所以我会详细写下我想要实现的目标、我在 Internet 上找到的内容,并展示我到目前为止所做的事情和我尝试过的事情。

我需要为我的应用程序添加拖放功能。我有要拖动到列表框项目的图像(基本上是控件)。

这是示例用户界面:

enter image description here

这是我现在的用法:

enter image description here

如您所见,我可以将四张图片中的一张拖放到列表框项目上。如果我将图像移到正确的目标(列表框图像)上,光标附近的图像会消失并且一切正常,但是当我不将图像放在列表项上(我释放鼠标)时,该图像会保留在屏幕上。

我的解决方案基于对 this 的回答问题,我无法删除不需要的窗口(光标附近的图像)

我的 XAML 如下所示:

<Window x:Class="DragDrop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Drag'n'Drop" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<ListBox HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Height="300" Margin="0,10,10,0" VerticalAlignment="Top" Width="234" ItemsSource="{Binding People}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" AllowDrop="True" PreviewDrop="UIElement_OnPreviewDrop">
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<ProgressBar Height="20" Value="{Binding Points}" Margin="0,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<Image HorizontalAlignment="Left" Height="72" Margin="10,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-60000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="10"/>
<Image HorizontalAlignment="Left" Height="72" Margin="87,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="20"/>
<Image HorizontalAlignment="Left" Height="72" Margin="10,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-7000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="30"/>
<Image HorizontalAlignment="Left" Height="72" Margin="87,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="40"/>
</Grid>
</Window>

和代码背后:

public partial class MainWindow
{
private readonly ObservableCollection<Person> _people = new ObservableCollection<Person>();

public ObservableCollection<Person> People
{
get { return _people; }
}

public MainWindow()
{
InitializeComponent();

_people.Add(new Person() {Name = "Person1", Points = 10});
_people.Add(new Person() {Name = "Person2", Points = 0});
_people.Add(new Person() {Name = "Person3", Points = 40});
}

private void OnMouseTouchDown(object sender, InputEventArgs e)
{
var item = sender as Image;
if (item == null) return;

var draggedItem = item;
var points = Convert.ToInt32(draggedItem.Tag);
CreateDragDropWindow(draggedItem);
System.Windows.DragDrop.DoDragDrop(draggedItem, points, DragDropEffects.Move);
}

private Window _dragdropWindow;

private void CreateDragDropWindow(Visual dragElement)
{
_dragdropWindow = new Window
{
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
AllowDrop = false,
Background = null,
IsHitTestVisible = false,
SizeToContent = SizeToContent.WidthAndHeight,
Topmost = true,
ShowInTaskbar = false
};

Rectangle r = new Rectangle
{
Width = ((FrameworkElement) dragElement).ActualWidth/2,
Height = ((FrameworkElement) dragElement).ActualHeight/2,
Fill = new VisualBrush(dragElement)
};
_dragdropWindow.Content = r;


Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);


_dragdropWindow.Left = w32Mouse.X;
_dragdropWindow.Top = w32Mouse.Y;
_dragdropWindow.Show();
}


[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;
};

private void UIElement_OnPreviewGiveFeedback(object sender, GiveFeedbackEventArgs e)
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);

_dragdropWindow.Left = w32Mouse.X;
_dragdropWindow.Top = w32Mouse.Y;
}

private void UIElement_OnPreviewDrop(object sender, DragEventArgs e)
{
//var droppedData = e.Data.GetData(typeof(Image)) as Image;
var droppedData = (Int32) e.Data.GetData(typeof (Int32));
var stackPanel = sender as StackPanel;
if (stackPanel != null)
{
var student = stackPanel.DataContext as Person;

//int targetIndex = _people.IndexOf(student);


if (student != null) student.Points += droppedData;
}
if (_dragdropWindow != null)
{
_dragdropWindow.Close();
_dragdropWindow = null;
}
}
}

public class Person : INotifyPropertyChanged
{
private string _name;
private int _points;

public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged();
}
}

public int Points
{
get { return _points; }
set
{
if (value == _points) return;
_points = value;
if (_points >= 100)
{
_points -= 100;
Debug.WriteLine("100!");
}
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}

我在互联网上发现我可以使用扩展 Adorner 的类,并且我找到了一些示例:

但它们都展示了如何从集合 (ItemsControls) 中拖动项目。第三个链接很有前途,但我无法采用它来满足我的需要。

所以我的问题是:

  1. 当我取消拖动(MouseUp 或不正确的拖动目标)时,如何隐藏示例中的小图像窗口
  2. 展示我使用 Adorner 以及如何在我的代码中使用它?我需要在我开始拖动时显示它,当我正确放置图像时隐藏它或者我取消拖放目标不正确

我刚开始使用 WPF,所以请尝试理解我的挫败感 - 我花了过去两个晚上和晚上试图让这个工作。

最佳答案

1) 修改您的 OnMouseTouchDown 处理程序以包括在开始拖动之前将 ContinueDragHandler 分配给拖动的项目,如下所示

 private void OnMouseTouchDown(object sender, InputEventArgs e)
{
var item = sender as FrameworkElement;
if (item == null) return;

var draggedItem = item;
var points = Convert.ToInt32(draggedItem.Tag);
CreateDragDropWindow(draggedItem);
System.Windows.DragDrop.AddQueryContinueDragHandler(draggedItem, DragContrinueHandler);
System.Windows.DragDrop.DoDragDrop(draggedItem, points, DragDropEffects.Move);
}

处理程序本身:

public void DragContrinueHandler(object sender, QueryContinueDragEventArgs e)
{
if (e.Action == DragAction.Continue && e.KeyStates != DragDropKeyStates.LeftMouseButton)
{
_dragdropWindow.Close();
}
}

2) 我认为创建一个新窗口来显示光标旁边的图像是一个肮脏的黑客行为。有很多关于通过拖放使用装饰器的文章。尽管您的方法可行并且不需要大量代码。另一方面,装饰品可以。我认为你应该创建另一个问题,如果你按照某些教程失败,请提供代码示例和你采取的步骤

关于c# - WPF 使用鼠标和触摸与 Adorner 一起拖放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32597184/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com