在同一页面上的两个重新排序列表框,防止用户之间拖放
本文关键字:列表 排序 拖放 之间 用户 一页 两个 新排序 | 更新日期: 2023-09-27 18:06:50
我有一个WPF c#应用程序,它有一个窗口,两个重新排序列表框紧挨着彼此。我使用这个链接中的示例来创建列表框用户控件。不幸的是,这允许用户从一个框中拖动并放入另一个框。我怎样才能确保这不会发生?
下面是我的代码: public void setItems(List<string> values){
_items = new ObservableCollection<Item>();
foreach (string s in values)
{
_items.Add(new Item(s));
}
listBox.DisplayMemberPath = "Name";
listBox.ItemsSource = _items;
listBox.PreviewMouseMove += ListBox_PreviewMouseMove;
var style = new Style(typeof(ListBoxItem));
style.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
style.Setters.Add(
new EventSetter(
ListBoxItem.PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(ListBoxItem_PreviewMouseLeftButtonDown)));
style.Setters.Add(
new EventSetter(
ListBoxItem.DropEvent,
new DragEventHandler(ListBoxItem_Drop)));
listBox.ItemContainerStyle = style;
}
private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point point = e.GetPosition(null);
Vector diff = _dragStartPoint - point;
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
var lb = sender as ListBox;
var lbi = FindVisualParent<ListBoxItem>(((DependencyObject)e.OriginalSource));
if (lbi != null)
{
DragDrop.DoDragDrop(lbi, lbi.DataContext, DragDropEffects.Move);
}
}
}
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_dragStartPoint = e.GetPosition(null);
}
private void ListBoxItem_Drop(object sender, DragEventArgs e)
{
if (sender is ListBoxItem)
{
var source = e.Data.GetData(typeof(Item)) as Item;
var target = ((ListBoxItem)(sender)).DataContext as Item;
int sourceIndex = listBox.Items.IndexOf(source);
int targetIndex = listBox.Items.IndexOf(target);
Debug.WriteLine("Target: " + targetIndex.ToString());
Move(source, sourceIndex, targetIndex);
}
}
private void Move(Item source, int sourceIndex, int targetIndex)
{
if (sourceIndex < targetIndex)
{
_items.Insert(targetIndex + 1, source);
_items.RemoveAt(sourceIndex);
}
else
{
int removeIndex = sourceIndex + 1;
if (_items.Count + 1 > removeIndex)
{
_items.Insert(targetIndex, source);
_items.RemoveAt(removeIndex);
}
}
}
}
我弄清楚了,以防其他人有类似的问题…
我将Move函数更改为:
private void Move(Item source, int sourceIndex, int targetIndex)
{
IList<Item> prevItems = _items;
try
{
_items.RemoveAt(sourceIndex);
_items.Insert(targetIndex, source);
}
catch(ArgumentOutOfRangeException)
{
//User doesn't need to be notified about this. It just means that they dragged out of the box they were ordering.
//The application does not need to be stopped when this happens.
_items = prevItems;
Debug.WriteLine("User tried to drag between boxes.. Order of boxes were not changed. ");
}
}
我意识到,如果我先删除项目,那么我就不必担心根据sourceIndex相对于targetIndex的位置更改目标或删除索引。相反,我可以将其包装在try catch中,并查找ArgumentOutOfRangeException,如果用户试图在两者之间拖放,就会发生这种情况。如果发生这种情况,我将重置为之前的项目。
据我所知,这个解决方案很好…也许有一种更简单的方法来解决这个问题。