【问题标题】:WPF C#: Rearrange items in listbox via drag and dropWPF C#:通过拖放重新排列列表框中的项目
【发布时间】:2011-03-21 23:32:42
【问题描述】:

我试图弄清楚如何通过鼠标拖动来上下移动预先填充的列表框中的项目。

我已经查看了 Microsoft api 中的 Control.DoDragDrop 方法,但我仍然无法让它做任何事情。

由于我是 Visual Studio 环境的新手,因此我将不胜感激。

【问题讨论】:

标签: c# wpf drag-and-drop


【解决方案1】:

我尝试使用 ObservableCollection 创建一个。看看吧。

    ObservableCollection<Emp> _empList = new ObservableCollection<Emp>();

    public Window1()
    {
        InitializeComponent();

        _empList .Add(new Emp("1", 22));
        _empList .Add(new Emp("2", 18));
        _empList .Add(new Emp("3", 29));
        _empList .Add(new Emp("4", 9));
        _empList .Add(new Emp("5", 29));
        _empList .Add(new Emp("6", 9));
        listbox1.DisplayMemberPath = "Name";
        listbox1.ItemsSource = _empList;
        
        Style itemContainerStyle = new Style(typeof(ListBoxItem));
        itemContainerStyle.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
        itemContainerStyle.Setters.Add(new EventSetter(ListBoxItem.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(s_PreviewMouseLeftButtonDown)));
        itemContainerStyle.Setters.Add(new EventSetter(ListBoxItem.DropEvent, new DragEventHandler(listbox1_Drop)));
        listbox1.ItemContainerStyle = itemContainerStyle;
    }

拖放过程:

    void s_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {

        if (sender is ListBoxItem)
        {
            ListBoxItem draggedItem = sender as ListBoxItem;
            DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
            draggedItem.IsSelected = true;
        }
    }

    void listbox1_Drop(object sender, DragEventArgs e)
    {
        Emp droppedData = e.Data.GetData(typeof(Emp)) as Emp;
        Emp target = ((ListBoxItem)(sender)).DataContext as Emp;

        int removedIdx = listbox1.Items.IndexOf(droppedData);
        int targetIdx = listbox1.Items.IndexOf(target);

        if (removedIdx < targetIdx)
        {
            _empList.Insert(targetIdx + 1, droppedData);
            _empList.RemoveAt(removedIdx);
        }
        else
        {
            int remIdx = removedIdx+1;
            if (_empList.Count + 1 > remIdx)
            {
                _empList.Insert(targetIdx, droppedData);
                _empList.RemoveAt(remIdx);
            }
        }
    }

注意:

  • 在这个实现中糟糕的一点是,由于它使用了PreviewMouseLeftButtonDown 事件,因此被拖动的项目看起来不像是选定的项目。
  • 此外,为了更容易实现,放置目标是列表框项目,而不是列表框本身 - 可能需要更好的解决方案。

【讨论】:

  • 如果将 PreviewMouseLeftButtonDown 更改为 PreviewMouseMoveEvent,然后将 e.LeftButton == MouseButtonState.Pressed 添加到 if 语句中,则可以解决选择问题。
  • 我需要将listbox1.Items.Refresh(); 添加到 Drop 处理程序的末尾,但除此之外,它的效果很好!
  • @tCoe - 初始化是什么意思?你可以做一个 ListBox listbox1 = new ListBox(),但你可以在 xaml 中做
  • @tCoe - 你的意思是你想订阅 xaml 中的 drop 事件而不是后面的代码?查看 IronRod 的答案,了解如何在下面执行此操作。但是,如果您根本不考虑任何代码,那么我认为您必须将其作为一种行为或其他东西。
  • @tCoe 将集合分配给列表框只需将其分配给 itemssource 属性 (listbox1.ItemsSource = _empList;)。关于错误,我认为您使用的是磨损事件,在我的代码中我使用的是 PreviewMouseLeftButtonDownEvent,它是 MouseButtonEventHandler 而不是 MouseEventHandler
【解决方案2】:

使用 dnr3 的答案,我创建了具有固定选择问题的版本。

Window1.xaml

<Window x:Class="ListBoxReorderDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ListBoxReorderDemo" Height="300" Width="300"
        WindowStartupLocation="CenterScreen">
    <Grid>
        <ListBox x:Name="listBox"/>
    </Grid>
</Window>

Window1.xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace ListBoxReorderDemo
{
    public class Item
    {
        public string Name { get; set; }
        public Item(string name)
        {
            this.Name = name;
        }
    }

    public partial class Window1 : Window
    {
        private Point _dragStartPoint;

        private T FindVisualParent<T>(DependencyObject child)
            where T : DependencyObject
        {
            var parentObject = VisualTreeHelper.GetParent(child);
            if (parentObject == null)
                return null;
            T parent = parentObject as T;
            if (parent != null)
                return parent;
            return FindVisualParent<T>(parentObject);
        }

        private IList<Item> _items = new ObservableCollection<Item>();

        public Window1()
        {
            InitializeComponent();

            _items.Add(new Item("1"));
            _items.Add(new Item("2"));
            _items.Add(new Item("3"));
            _items.Add(new Item("4"));
            _items.Add(new Item("5"));
            _items.Add(new Item("6"));

            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);

                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);
                }
            }
        }
    }
}

支持泛型和数据绑定的版本。

Window1.xaml

<Window x:Class="ListBoxReorderDemo.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ListBoxReorderDemo"
        Title="ListBoxReorderDemo" Height="300" Width="300"
        WindowStartupLocation="CenterScreen">
    <Grid>
        <local:ItemDragAndDropListBox x:Name="listBox" ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </local:ItemDragAndDropListBox>
    </Grid>
</Window>

Window1.xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace ListBoxReorderDemo
{
    public class DragAndDropListBox<T> : ListBox 
        where T : class
    {
        private Point _dragStartPoint;

        private P FindVisualParent<P>(DependencyObject child) 
            where P : DependencyObject
        {
            var parentObject = VisualTreeHelper.GetParent(child);
            if (parentObject == null)
                return null;

            P parent = parentObject as P;
            if (parent != null)
                return parent;

            return FindVisualParent<P>(parentObject);
        }

        public DragAndDropListBox()
        {
            this.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)));

            this.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(T)) as T;
                var target = ((ListBoxItem)(sender)).DataContext as T;

                int sourceIndex = this.Items.IndexOf(source);
                int targetIndex = this.Items.IndexOf(target);

                Move(source, sourceIndex, targetIndex);
            }
        }

        private void Move(T source, int sourceIndex, int targetIndex)
        {
            if (sourceIndex < targetIndex)
            {
                var items = this.DataContext as IList<T>;
                if (items != null)
                {
                    items.Insert(targetIndex + 1, source);
                    items.RemoveAt(sourceIndex);
                }
            }
            else
            {
                var items = this.DataContext as IList<T>;
                if (items != null)
                {
                    int removeIndex = sourceIndex + 1;
                    if (items.Count + 1 > removeIndex)
                    {
                        items.Insert(targetIndex, source);
                        items.RemoveAt(removeIndex);
                    }
                }
            }
        }
    }

    public class Item
    {
        public string Name { get; set; }
        public Item(string name)
        {
            this.Name = name;
        }
    }

    public class ItemDragAndDropListBox : DragAndDropListBox<Item> { }

    public partial class Window1 : Window
    {
        private IList<Item> _items = new ObservableCollection<Item>();

        public Window1()
        {
            InitializeComponent();

            _items.Add(new Item("1"));
            _items.Add(new Item("2"));
            _items.Add(new Item("3"));
            _items.Add(new Item("4"));
            _items.Add(new Item("5"));
            _items.Add(new Item("6"));

            listBox.DataContext = _items;
        }
    }
}

【讨论】:

  • 这确实非常好,感谢您和@dnr3。我能看到的唯一可以改进的是,如果光标在拖动时可以悬停在没有文件的列表框部分上。实际上,如果拖动得太低,光标将变为空集,无拖动符号。我想如果你可以拖动多个项目。不是我在抱怨,这已经足够开始了。
  • 我对这个解决方案有一个小问题,因为您在单击鼠标按钮时存储拖动位置,但您在鼠标移动中搜索项目。这意味着在某些情况下,如果您单击项目的边缘,您在鼠标移动事件中找到的项目与实际单击的项目不同。我更改了逻辑以在鼠标按下事件中搜索单击的项目并将其存储在一个变量中,在鼠标移动事件中我使用先前存储的单击项目来防止这种边缘情况
【解决方案3】:

我建议使用名为GongSolutions.WPF.DragDrop 的拖放行为。它允许 MVVM 风格的用例使用附加的属性设置器来启用它,而无需在视图中隐藏代码。您应该查看链接以获取一个简单的示例。

【讨论】:

  • 虽然我通常不喜欢为如此狭窄的用例(拖放)添加库,但您链接到的库似乎经过深思熟虑和完整。同时,如果一个人想要一个体面的、完整的实现,正确拖放的代码量是惊人的大。实际上,我可能会破例并使用您链接到的库。谢谢!
  • 这个库真的很不错!我会向任何需要使用拖放来完成比基础更复杂的事情的人推荐这个,即使是这样。
  • 很棒的库非常简单
  • @rawpower 我同意这个库很棒,我想补充一点,我非常喜欢添加一个用例狭窄的库,而不是尝试修复或增强所有内容的库。这只适用于只使用一个库,但可以尝试 DevExpress 与 Telerik 和 Infragistics 以及 Prism 例如...
【解决方案4】:

我接受了 dnr3 的答案并对其进行了修改,以便在 XAML 中实现。结果相同,只是更喜欢在 XAML 中而不是在代码隐藏中做我能做的。

代替代码隐藏:

Style itemContainerStyle = new Style(typeof(ListBoxItem));
itemContainerStyle.Setters.Add(new Setter(AllowDropProperty, true));
itemContainerStyle.Setters.Add(new EventSetter(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(s_PreviewMouseLeftButtonDown)));
itemContainerStyle.Setters.Add(new EventSetter(DropEvent, new DragEventHandler(listbox1_Drop)));
listbox1.ItemContainerStyle = itemContainerStyle;

把它放在 XAML 中:

<Window.Resources>
    <Style x:Key="ListBoxDragDrop" TargetType="{x:Type ListBoxItem}">
        <Setter Property="AllowDrop" Value="true"/>
        <EventSetter Event="PreviewMouseMove" Handler="s_PreviewMouseMoveEvent"/>
        <EventSetter Event="Drop" Handler="listbox1_Drop"/>
    </Style>
</Window.Resources>
<Grid>
    <ListBox x:Name="listbox1" ItemContainerStyle="{StaticResource ListBoxDragDrop}" HorizontalAlignment="Left" Height="299" Margin="10,10,0,0" VerticalAlignment="Top" Width="224"/>
</Grid>

这是放置在 XAML 代码隐藏中的鼠标处理程序。

void s_PreviewMouseMoveEvent(object sender, MouseEventArgs e)
{
    if (sender is ListBoxItem && e.LeftButton == MouseButtonState.Pressed)
    {
        ListBoxItem draggedItem = sender as ListBoxItem;
        DragDrop.DoDragDrop(draggedItem, draggedItem.DataContext, DragDropEffects.Move);
        draggedItem.IsSelected = true;
    }
}

【讨论】:

  • 您能分享一下您的处理程序对于鼠标按钮事件处理程序的外观吗?
【解决方案5】:

修复代码:

private void listbox1_Drop(object sender, DragEventArgs e)
{
    if (sender is ListBoxItem)
    {
        Emp droppedData = e.Data.GetData(typeof(Emp)) as Emp;
        Emp target = ((ListBoxItem)(sender)).DataContext as Emp;

        int removedIdx = listbox1.Items.IndexOf(droppedData);
        int targetIdx = listbox1.Items.IndexOf(target);

        if (removedIdx < targetIdx)
        {
            _empList.Insert(targetIdx + 1, droppedData);
            _empList.RemoveAt(removedIdx);
        }
        else
        {
            int remIdx = removedIdx + 1;
            if (_empList.Count + 1 > remIdx)
            {
                _empList.Insert(targetIdx, droppedData);
                _empList.RemoveAt(remIdx);
            }
        }
    }
}

【讨论】:

    【解决方案6】:

    这对我很有帮助,谢谢。尤其是泛型版本。

    我做了以下修改:

    因为我没有设置 ListBox 的 DataContext(只是 ItemsSource),所以我使用

    var items = this.ItemsSource as IList<T>;
    

    在 Move 方法中。

    在“移动”的末尾我添加了:

    this.SelectedItem = source;
    

    因为我希望用户将移动的项目作为当前选择。

    【讨论】:

      【解决方案7】:

      改进了 Wiesław Šoltésdnr3 答案的修改,我将其抽象为一个易于重用的类,以便您可以设置多个只有几行代码的列表。我还添加了一项功能,让每个项目在 2 种背景颜色之间交替,以便于查看(尽管如果您不想要,可以轻松删除此功能)。

      F.Y.I:对不起,如果你是 'var' 的爱好者,但我绝对不是,那些已被我的 IDE 删除,我不打算将它们放回去。当然,这对实际程序行为没有任何改变,无论如何都应该改善编译时间,所以.. 赢了! :p

      这是课程:

      /// <typeparam name="IT">The item type to be stored in this list</typeparam>
      internal class ReorderableList<IT> where IT : class
      {
          private readonly SolidColorBrush m_alternator1, m_alternator2; // Background colours for the list items to alternate between
          private readonly ListBox m_ListBox; // The target ListBox we're modifying
          private readonly string m_displayMemberPath; // The name of the member in to display 
          private readonly IList<IT> m_items = new ObservableCollection<IT>();
          private Point m_cursorStartPos;
      
          /// <summary>
          /// Initializes the list (this must be done after components are initialized and loaded!).
          /// </summary>
          /// <param name="resourceProvider">Pass 'this' for this parameter</param>
          /// <param name="listBox">The target ListBox control to modify</param>
          /// <param name="displayMemberPath">The name of the member in the generic type contained in this list, to be displayed</param>
          public ReorderableList(ListBox listBox, string displayMemberPath, SolidColorBrush alternator1, SolidColorBrush alternator2)
          {
              m_ListBox = listBox;
              m_displayMemberPath = displayMemberPath;
              m_alternator1 = alternator1;
              m_alternator2 = alternator2;
      
              Initialize();
          }
      
          private void Initialize()
          {
              // Set the list box's items source and tell it what member in the IT class to use for the display name
              // Add an event handler for preview mouse move
      
              m_ListBox.DisplayMemberPath = m_displayMemberPath;
              m_ListBox.ItemsSource = m_items;
              m_ListBox.PreviewMouseMove += OnListPreviewMouseMove;
      
              // Create the item container style to be used by the listbox
              // Add mouse event handlers to the style
      
              Style style = new Style(typeof(ListBoxItem));
              style.Setters.Add(new Setter(UIElement.AllowDropProperty, true));
              style.Setters.Add(new EventSetter(UIElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(OnListPreviewMouseLeftButtonDown)));
              style.Setters.Add(new EventSetter(UIElement.DropEvent, new DragEventHandler(OnListDrop)));
      
              // Add triggers to alternate the background colour of each element based on its alternation index
              // (Remove this, as well as the two SolidColorBrush resources if you don't want this feature)
      
              Trigger trigger1 = new Trigger()
              {
                  Property = ItemsControl.AlternationIndexProperty,
                  Value = 0
              };
      
              Setter setter1 = new Setter()
              {
                  Property = Control.BackgroundProperty,
                  Value = m_alternator1
              };
      
              trigger1.Setters.Add(setter1);
              style.Triggers.Add(trigger1);
      
              Trigger trigger2 = new Trigger()
              {
                  Property = ItemsControl.AlternationIndexProperty,
                  Value = 1
              };
      
              Setter setter2 = new Setter()
              {
                  Property = Control.BackgroundProperty,
                  Value = m_alternator2
              };
      
              trigger2.Setters.Add(setter2);
              style.Triggers.Add(trigger2);
      
              // Set the item container style
      
              m_ListBox.ItemContainerStyle = style;
          }
      
          /// <summary>
          /// Adds an item to the list. If [ignoreDuplicates] is false and the item is already in the list,
          /// the item won't be added.
          /// </summary>
          /// <param name="item">The item to add</param>
          /// <param name="ignoreDuplicates">Whether or not to add the item regardless of whether it's already in the list</param>
          /// <returns>Whether or not the item was added</returns>
          public bool Add(IT item, bool ignoreDuplicates = true)
          {
              if (!ignoreDuplicates && Contains(item)) return false;
      
              m_items.Add(item);
              return true;
          }
      
          /// <summary>
          /// Removes an item from the list.
          /// </summary>
          /// <param name="item">The item to remove</param>
          /// <returns>Whether or not the item was removed from the list. This will be false if the item was not in the list to begin with.</returns>
          public bool Remove(IT item)
          {
              if (Contains(item)) return false;
      
              m_items.Remove(item);
              return true;
          }
      
          /// <summary>
          /// Returns whether or not the list contains the given item.
          /// </summary>
          /// <param name="item">The item to check for</param>
          /// <returns>Whether or not the list contains the given item.</returns>
          public bool Contains(IT item)
          {
              return m_items.Contains(item);
          }
      
          private void OnListPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
          {
              m_cursorStartPos = e.GetPosition(null);
          }
      
          private void OnListPreviewMouseMove(object sender, MouseEventArgs e)
          {
              Point currentCursorPos = e.GetPosition(null);
              Vector cursorVector = m_cursorStartPos - currentCursorPos;
      
              if (e.LeftButton == MouseButtonState.Pressed
                  &&(Math.Abs(cursorVector.X) > SystemParameters.MinimumHorizontalDragDistance
                  || Math.Abs(cursorVector.Y) > SystemParameters.MinimumVerticalDragDistance))
              {
                  ListBoxItem targetItem = FindVisualParent<ListBoxItem>(((DependencyObject)e.OriginalSource));
                  if (targetItem != null)
                  {
                      DragDrop.DoDragDrop(targetItem, targetItem.DataContext, DragDropEffects.Move);
                  }
              }
          }
      
          private void OnListDrop(object sender, DragEventArgs e)
          {
              if (sender is ListBoxItem item)
              {
                  IT source = e.Data.GetData(typeof(IT)) as IT;
                  IT target = item.DataContext as IT;
      
                  int sourceIndex = m_ListBox.Items.IndexOf(source);
                  int targetIndex = m_ListBox.Items.IndexOf(target);
      
                  Move(source, sourceIndex, targetIndex);
              }
          }
      
          private void Move(IT source, int sourceIndex, int targetIndex)
          {
              if (sourceIndex < targetIndex)
              {
                  m_items.Insert(targetIndex + 1, source);
                  m_items.RemoveAt(sourceIndex);
              }
              else
              {
                  int removeIndex = sourceIndex + 1;
                  if (m_items.Count + 1 > removeIndex)
                  {
                      m_items.Insert(targetIndex, source);
                      m_items.RemoveAt(removeIndex);
                  }
              }
          }
      
          private T FindVisualParent<T>(DependencyObject child) where T : DependencyObject
          {
              DependencyObject parentObject = VisualTreeHelper.GetParent(child);
              if (parentObject == null) return null;
              if (parentObject is T parent) return parent;
      
              return FindVisualParent<T>(parentObject);
          }
      }
      

      这是一个示例 IT(项目类型)类(与原始答案相同):

      public class ExampleItem
      {
          public string Name { get; set; }
      
          public ExampleItem(string name)
          {
              Name = name;
          }
      }
      

      最后是用法:

      public partial class MainWindow : Window
      {
          private readonly ReorderableList<ExampleItem> ExampleList;
      
          public MainWindow()
          {
              InitializeComponent();
      
              ExampleList = new ReorderableList<ExampleItem>(myXamlListBoxControl, "Name",
                  FindResource("AlternatingBG1") as SolidColorBrush,
                  FindResource("AlternatingBG2") as SolidColorBrush);
      
              ExampleList.Add(new ExampleItem("Test Item 1"));
              ExampleList.Add(new ExampleItem("Test Item 2"));
              ExampleList.Add(new ExampleItem("Test Item 3"));
              ExampleList.Add(new ExampleItem("Test Item 4"));
              ExampleList.Add(new ExampleItem("Test Item 5"));
              ExampleList.Add(new ExampleItem("Test Item 6"));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-25
        • 2020-04-05
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        • 1970-01-01
        相关资源
        最近更新 更多