gpt4 book ai didi

c# - 一般拖放 ListBoxItems

转载 作者:行者123 更新时间:2023-12-03 10:52:28 25 4
gpt4 key购买 nike

我想在数据绑定(bind)的多个列表框上实现拖放 - 使用 MVVM 模式。我不是试图在列表框之间拖放,而是希望用户能够在每个列表框中拖放列表框项,以便他们可以重新排列排序顺序。我在 SO 上发现这篇文章非常有帮助:

WPF C#: Rearrange items in listbox via drag and drop

我想尝试使这些方法更“通用”,以便它可以在绑定(bind)到不同类型的 Observable 集合的任何列表框上工作。所以说这是我在 VIEW 中的 XAML:

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">

<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ListBoxItemDragDrop">
<Setter Property="AllowDrop" Value="True" />
<EventSetter Event="PreviewMouseMove" Handler="ListBoxItem_PreviewMouseMoveEvent" />
<EventSetter Event="Drop" Handler="listbox1_Drop" />
</Style>
</Window.Resources>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<ListBox Name="listbox1"
ItemsSource="{Binding OCofType1}"
ItemContainerStyle="{StaticResource ListBoxItemDragDrop}" />

<ListBox Name="listbox2" Grid.Column="1"
ItemsSource="{Binding OCofType2}"
ItemContainerStyle="{StaticResource ListBoxItemDragDrop}"/>
</Grid>

</Window>

其中 OC 绑定(bind)是 ObservalbeCollection 和 ObservalbeCollection 。这是 VIEW 中抓取鼠标移动事件并检查它是否为拖动的方法:
void ListBoxItem_PreviewMouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && sender is ListBoxItem)
{
ListBoxItem draggedItem = (ListBoxItem)sender;
DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
draggedItem.IsSelected = true;
}
}

这似乎足够“通用”。接下来是方法,也在 VIEW 中,处理 drop ,这就是我卡住的地方:
void ListBoxItem_Drop(object sender, DragEventArgs e)
{
object Target = ((ListBoxItem)(sender)).DataContext;
object Dropped = e.Data.GetData(Target.GetType());

int RemoveIndex = listbox1.Items.IndexOf(Dropped);
int TargetIndex = listbox1.Items.IndexOf(Target);

ListBox container = ((DependencyObject)sender).GetAncestor<ListBox>();

if (RemoveIndex < TargetIndex)
{
//THESE WILL NOT WORK IF I AM DOING BINDINGS THROUGH THE ITEMSSOURCE
//container.Items.Insert(RemoveIndex + 1, Dropped);
//container.Items.RemoveAt(RemoveIndex);

//SO HAVE TO USE THE ITEMSSOURCE DIRECTLY BUT HOW WITHOUT A SPECIFIC CAST TO THE OC<TYPE#>
container.ItemsSource.Insert(RemoveIndex + 1, Dropped); //ERROR: IENUMERATOR DOES NOT CONTAIN A DEFINITION FOR INSERT....
container.ItemsSource.RemoveAt(RemoveIndex); //ERROR: IENUMERATOR DOES NOT CONTAIN A DEFINITION FOR REMOVEAT....
}
else
if (container.Items.Count > RemoveIndex)
{
//THESE WILL NOT WORK IF I AM DOING BINDINGS THROUGH THE ITEMSSOURCE
//container.Items.Insert(TargetIndex, Dropped);
//container.Items.RemoveAt(RemoveIndex + 1);

//SO HAVE TO USE THE ITEMSSOURCE DIRECTLY BUT HOW WITHOUT A SPECIFIC CAST TO THE OC<TYPE#>
container.ItemsSource.Insert(TargetIndex, Dropped); //ERROR: IENUMERATOR DOES NOT CONTAIN A DEFINITION FOR INSERT....
container.ItemsSource.RemoveAt(RemoveIndex + 1); //ERROR: IENUMERATOR DOES NOT CONTAIN A DEFINITION FOR REMOVEAT....

}
}

查找祖先函数是这样的(来自 SO 上的另一篇文章):
static T FindAnchestor<T>(DependencyObject current) where T : DependencyObject
{
do
{
if (current is T)
return (T)current;

current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}

在 drop 函数中,如果我直接添加到 ListBox 的 List 集合中,这可能会起作用。但由于我在 VIEWMODEL 中对集合进行绑定(bind),因此会出错,说我必须通过 ItemsSource 处理这些对象。但是,如果我使用 ItemsSource,我将不得不为每个 OC 类型制作函数的可变版本,因为我不会在运行时也转换 ItemsSource。我可以使用 if 语句将其保留为 1 个函数,该语句确定将其显式转换为什么,但不必记住更新它是否适用于每个新的 OC 会更干净。

那么问题是如何在不确切知道要转换什么的情况下将项目添加/移动到 ItemsSource?

谢谢你的帮助。

最佳答案

这是一个非常方便的工具/框架。 Gong WPF Drag & Drop

关于c# - 一般拖放 ListBoxItems,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19936149/

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