8

我有一个堆栈面板,其中包含一些在运行时添加或删除的用户控件。这些元素有一个索引,我在新建它们时分配给它们,我需要保持这些元素按该索引排序,所以我写了一个快速排序函数,它根据索引对它们进行排序,但在进行交换的行上

          y = items[i]; //y is a temp variable
          items[i] = items[j];

我明白了

“指定索引已在使用中。首先断开指定索引处的 Visual 子级”

我尝试将它们复制到临时变量,从集合中删除它们,然后使用 UIElementCollection 中的 Insert 函数将它们分配给它们的正确索引,但后来我得到了

“指定的视觉对象已经是另一个视觉对象的子对象或 CompositionTarget 的根”

是否有我需要的克隆元素或我在某处缺少的东西?

4

4 回答 4

11

为什么不使用 ListBox/ItemsSontrol 并在其上使用 CollectionViewSorce/SortDescription 来完成这项工作。将元素添加到像 stackpanel 这样的 LayOut 面板并不是 WPF 应用程序的有效方式。垂直方向的 StackPanel 是 ListBox/ItemsControl 的默认设置,但如果你想要一些不同的布局,你总是可以覆盖 ListBox.ItemsPanel 模板

如果您可以遵循MVVM方法,那么只需在 ViewModel 类中指定一个属性(在您的情况下它将是Index)并在 listBox 级别设置 SortDescription 将自动为您提供此功能。无需添加和删除实际的 UIElement,您只需添加/删除绑定到 ListBox.ItemsSource 的 ObservableCollection。并指定适当的 DataTemplate。

如果您不熟悉 CollectionViewSource,请检查此 - http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.sortdescriptions.aspx

并且代码将更像下面......它非常简单。

   <UserControl.Resources>
    <CollectionViewSource x:Key="sourceCollection" Source="{Binding YourObservableCollectionProperty}">
       <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="YourProperty-Index"/>
       </CollectionViewSource.SortDescriptions>
     </CollectionViewSource>
   </UserControl.Resources>       

  <ItemsControl ItemsSource="{Binding Source={StaticResource sourceCollection}}"/>

注意:<--xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"-->

于 2010-03-03T17:14:37.927 回答
5

上面的答案是正确的,但是如果你不能改变你的堆栈面板(如果你没有足够的时间,或者已经写了很多与堆栈面板相关的代码)试试这个:

  1. 将控件存储在列表或字典中
  2. 对列表或字典进行排序
  3. 使用 StackPanel.Children.Remove(child) 从 stackpanel 中删除控件
  4. List 或 Dictionary 的 Foreach 成员使用以下方法向 StackPanel 添加控件: StackPanel.Children.Insert(i, child);

注意:代码正在运行,Remove 函数从 StackPanel 项(从树中)中删除控件,但控件已经在内存中,以便控件能够插入任何 StackPanel 或相同的 StackPanel。

于 2011-08-19T16:35:53.680 回答
1

如果你想这样做,你需要确保 Parent 为空,并且你的面板索引没有被使用。

如果你只是把它换成一个临时变量,它仍然是同一个引用。

使用 Visual Tree Helper 来取消或移动您的 UIElement。

于 2010-03-03T17:56:44.243 回答
0

如果您给每个元素特定的名称(即索引)。当您删除此控件时,您可以重命名结果控件。

之后,您的所有控件都将被排序。

于 2010-03-03T17:45:36.607 回答