ItemsControl拖放 [英] ItemsControl Drag and Drop
问题描述
我有一个ItemControl与DataTemplate绑定到一个ObservableCollection的整数。
< ItemsControl Name =DimsContainer ItemTemplate ={StaticResource DimensionsTemplate}>
< ItemsControl.ItemsPanel>
< ItemsPanelTemplate>
< StackPanel Orientation =Horizontal/>
< / ItemsPanelTemplate>
< /ItemsControl.ItemsPanel>
< / ItemsControl>
在Windows资源中:
< Window.Resources>
< DataTemplate x:Key =DimensionsTemplate>
< TextBlock Text ={Binding}
Padding =5
VerticalAlignment =Center
FontSize =32/>
< / DataTemplate>
< /Window.Resources>
我试图实现拖放ItemsControl内的项目的能力(即能够重新排序整数)。有没有人有一个简单的例子,如何做到这一点?我连接了PreviewMouseMove,DragEnter和Drop事件。问题是我无法确定如何确定哪个项目被拖动以及拖动到哪个项目。看来整个ItemsControl都被传入事件。
这是一个我如何做到的例子。 p>
XAML:
< Window.DataContext>
< local:MyViewModel />
< /Window.DataContext>
< Grid>
< ScrollViewer>
< ListView ItemsSource ={Binding MyData}HorizontalAlignment =StretchName =listviewScrollViewer.PanningMode =VerticalOnly>
< ListView.ItemTemplate>
< DataTemplate>
< Button Content ={Binding}
Command ={Binding DataContext.MyCommand,RelativeSource = {RelativeSource AncestorType = ItemsControl}}
CommandParameter ={Binding}
Margin =5 2Width =150Height =50
FontSize =30/>
< / DataTemplate>
< /ListView.ItemTemplate>
< ListView.Resources>
< Style TargetType =Button>
< EventSetter Event =PreviewMouseMoveHandler =PreviewMouseMove/>
< EventSetter Event =DropHandler =Drop/>
< Setter Property =AllowDropValue =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, ,五,六,七,八,九,十,二十八,十一,十四,十五, 十六,十七,十八,十九,二十,
});
}
}
public ICommand MyCommand {get;私人集合}
私有类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()); }
}
}
事件: em>
private void Drop(object sender,DragEventArgs e)
{
var source = e.Data.GetData(Source)as string;
if(source!= null)
{
int newIndex = listview.Items.IndexOf((发件人为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 Action(()=>
{
if(e.LeftButton == MouseButtonState.Pressed)
{
var data = new DataObject();
data。 SetData(Source,(sender as Button).Content);
DragDrop.DoDragDrop(发件人为DependencyObject,data,DragDropEffects.Move);
e.Handled = true;
}
}),null);
}), CancellationToken.None);
}
}
上面的例子是一个复杂的原因, code>列表是一个按钮
和按钮
点击
我也要做一些动作。 您的情况相对容易。
对许多开发者来说,丢弃可能会令人困惑。但是低于
是一些要点:
使用
PreviewMouseMove
事件实际上开始一个拖动和处理程序使用DragDrop.DoDragDrop
事件来提高DragDrop
相关
事件和游标
。发件人
参数是
的元素,目前在这种情况下,目标是$ code> UIElement 那是
被拖动。
使用
DragEnter
&如果要更改Mouse
当前正在拖动的元素的视觉效果,DragOver
事件。发件人
参数是当前拖动的元素,只是
结束拖拽状态。
使用
删除
事件来处理已删除的元素。发件人
参数是Drop发生的元素。
使用
DataObject
对象在这些事件之间传递信息。该类的SetData
方法用于在此中添加数据。这个方法
有两个参数,它们像key-value
对一样工作。一旦设置你
可以通过使用
GetData
在下一个被调用的事件DragDrop
通过传递键
作为参数。 (即
e.Data.GetData(Source)
)
这里是一个相关的帖子。
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>
And in the Windows Resources:
<Window.Resources>
<DataTemplate x:Key="DimensionsTemplate" >
<TextBlock Text="{Binding}"
Padding="5"
VerticalAlignment="Center"
FontSize="32"/>
</DataTemplate>
</Window.Resources>
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()); }
}
}
Events:
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);
}
}
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.
Drag & Drop can be confusing for many developers. But below are the some key points how to do it:
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.Use
DragEnter
&DragOver
event if want to change the visual of element over which theMouse
is currently dragging.sender
argument is the element that has currently dragged over / that just ended drag over situation.Use
Drop
event to handle the dropped element.sender
argument is the element on which the Drop happened.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 likekey-value
pair. Once set you can get this data in next called event ofDragDrop
by usingGetData
method by passing thekey
as argument. (i.e.e.Data.GetData("Source")
)
Here is a relative post.
这篇关于ItemsControl拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!