Ответ 1
Вот пример того, как я это сделал.
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
мне также нужно выполнить некоторые действия. Ваш случай относительно прост.
Перетаскивание может быть запутанным для многих разработчиков. Но ниже некоторые ключевые моменты, как это сделать:
Используйте
PreviewMouseMove
событие, чтобы на самом деле начать перетаскивание и использовать обработчикDragDrop.DoDragDrop
для повышенияDragDrop
. событий иCursors
. Аргументsender
- это элемент, который имеет в данный момент захватил мышь в этом случаеUIElement
, который перетаскивается.Используйте
DragEnter
иDragOver
событие, если хотите изменить визуальность элемента, по которому в настоящее время перетаскиваетсяMouse
.sender
Аргумент - это элемент, который в настоящее время перетаскивается/что просто закончил перетаскивание ситуации.Используйте
Drop
событие для обработки сброшенного элемента. Аргументsender
- это элемент, на котором произошло падение.Используйте объект
DataObject
для передачи информации между этими событиями.SetData
метод класса используется для добавления данных в это. Этот метод имеет два аргумента, и они работают как параkey-value
. Как только вы установите может получить эти данные в следующем вызываемом событииDragDrop
, используяGetData
, передав аргументkey
в качестве аргумента. (Т.е.e.Data.GetData("Source")
)
Здесь - относительный пост.