问题描述
我有一个带有 DataTemplate 的 ItemsControl,它绑定到整数的 ObservableCollection.
I have an ItemsControl with a DataTemplate that is bound to an ObservableCollection of integers.
<ItemsControl Name="DimsContainer" ItemTemplate="{StaticResource DimensionsTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
在 Windows 资源中:
And in the Windows Resources:
<Window.Resources>
<DataTemplate x:Key="DimensionsTemplate" >
<TextBlock Text="{Binding}"
Padding="5"
VerticalAlignment="Center"
FontSize="32"/>
</DataTemplate>
</Window.Resources>
我正在尝试实现在 ItemsControl 中拖放项目的能力(即能够对整数重新排序).有没有人有一个简单的例子来说明如何做到这一点?我连接了 PreviewMouseMove、DragEnter 和 Drop 事件.问题是我无法弄清楚如何确定正在拖动哪个项目以及将其拖动到哪里.似乎整个 ItemsControl 都被传递到了事件中.
I'm trying to implement the ability to drag and drop items within the ItemsControl (i.e. to be able to reorder the integers). Does anyone have a simple example of how to do this? I hooked up the PreviewMouseMove, DragEnter and Drop events. The problem is that I can't figure out how to determine which item is being dragged and where it is dragged to. It seems that the entire ItemsControl gets passed into the events.
推荐答案
这是我如何做到的示例.
Here is an example how I've done it.
XAML:
<Window.DataContext>
<local:MyViewModel />
</Window.DataContext>
<Grid>
<ScrollViewer>
<ListView ItemsSource="{Binding MyData}" HorizontalAlignment="Stretch" Name="listview" ScrollViewer.PanningMode="VerticalOnly">
<ListView.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}"
Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
Margin="5 2" Width="150" Height="50"
FontSize="30" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Resources>
<Style TargetType="Button">
<EventSetter Event="PreviewMouseMove" Handler="PreviewMouseMove" />
<EventSetter Event="Drop" Handler="Drop" />
<Setter Property="AllowDrop" Value="True" />
</Style>
</ListView.Resources>
</ListView>
</ScrollViewer>
</Grid>
ViewModel:
class MyViewModel
{
public MyViewModel()
{
MyCommand = new ICommandImplementation();
}
public ObservableCollection<string> MyData
{
get
{
return new ObservableCollection<string>(new string[]{
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"
});
}
}
public ICommand MyCommand { get; private set; }
private class ICommandImplementation : ICommand
{
public bool CanExecute(object parameter) { return true; }
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); }
}
}
事件:
private void Drop(object sender, DragEventArgs e)
{
var source = e.Data.GetData("Source") as string;
if (source != null)
{
int newIndex = listview.Items.IndexOf((sender as Button).Content);
var list = listview.ItemsSource as ObservableCollection<string>;
list.RemoveAt(list.IndexOf(source));
list.Insert(newIndex, source);
}
}
private void PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Task.Factory.StartNew(new Action(() =>
{
Thread.Sleep(500);
App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var data = new DataObject();
data.SetData("Source", (sender as Button).Content);
DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move);
e.Handled = true;
}
}), null);
}), CancellationToken.None);
}
}
上面的例子有点复杂,因为 list
的每个项目都是一个 Button
并且在 Button
click
我也得做一些动作.你的案子比较简单.
Above example is a little complex cause every item of list
is a Button
and on Button
click
I also have to do some action. Your case is relatively easy.
拖动 &Drop 可能会让许多开发人员感到困惑.但在下面是一些关键点如何做到这一点:
Drag & Drop can be confusing for many developers. But below are the some key points how to do it:
使用
PreviewMouseMove
事件实际开始拖动,并在处理程序中使用DragDrop.DoDragDrop
事件引发DragDrop
相关事件和游标
.sender
参数是具有在这种情况下,当前捕获的鼠标UIElement
是被拖了.
Use
PreviewMouseMove
event to actually start a drag and in handler useDragDrop.DoDragDrop
event to raiseDragDrop
related events andCursors
.sender
argument is the element that has captured the mouse currently in this case theUIElement
that is being dragged.
使用 DragEnter
&DragOver
事件,如果想要更改 Mouse
当前拖动的元素的视觉效果.发件人
参数是当前拖过/的元素结束拖拽情况.
Use DragEnter
& DragOver
event if want to change the visual of element over which the Mouse
is currently dragging. sender
argument is the element that has currently dragged over / that just
ended drag over situation.
使用 Drop
事件来处理被放置的元素.sender
参数是 Drop 发生的元素.
Use Drop
event to handle the dropped element. sender
argument is the element on which the Drop happened.
使用 DataObject
对象在这些事件之间传递信息.类的SetData
方法用于在其中添加数据.这种方法有两个参数,它们像 key-value
对一样工作.一旦设置你可以通过使用在 DragDrop
的下一个调用事件中获取此数据GetData
方法,通过传递 key
作为参数.(IE.e.Data.GetData("Source")
)
Use DataObject
object to pass info between these events. SetData
method of the class is used to add data in this. This method
has two arguments, and they work like key-value
pair. Once set you
can get this data in next called event of DragDrop
by using
GetData
method by passing the key
as argument. (i.e.
e.Data.GetData("Source")
)
这里是一个相对的帖子.
这篇关于ItemsControl 拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!