我有一个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);
}
}
}
}
我想通了,以防其他人遇到类似的问题...
我将移动功能更改为以下内容:
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,如果用户尝试在它们之间拖放,则会发生这种情况。如果发生这种情况,我会将框重置为之前的项目。
据我所知,此解决方案效果很好...可能有一种更简单的方法可以解决此问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句