C# stackpanel WPF中的排序元素

C# stackpanel WPF中的排序元素,c#,wpf,sorting,stackpanel,C#,Wpf,Sorting,Stackpanel,我有一个stackpanel,其中包含一些在运行时添加或删除的用户控件。 这些元素有一个索引,当我新建它们时,我会分配给它们,我需要让这些元素按照索引排序,所以我编写了一个快速排序函数,根据索引对它们进行排序 但是在交换的线路上 y = items[i]; //y is a temp variable items[i] = items[j]; 我明白了 “指定的索引已在使用中。请先断开指定索引处的可视子级” 我尝试将它们复制到一个临时变量中,从集合中删除

我有一个stackpanel,其中包含一些在运行时添加或删除的用户控件。 这些元素有一个索引,当我新建它们时,我会分配给它们,我需要让这些元素按照索引排序,所以我编写了一个快速排序函数,根据索引对它们进行排序 但是在交换的线路上

          y = items[i]; //y is a temp variable
          items[i] = items[j];
我明白了

“指定的索引已在使用中。请先断开指定索引处的可视子级”

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

“指定的Visual已经是另一个Visual的子级或CompositionTarget的根”


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

为什么不使用ListBox/ItemsControl并使用CollectionViewSorce/SortDescription来完成这项工作。在WPF应用程序中,向布局面板(如stackpanel)添加元素不是一种有效的方式。具有垂直方向的StackPanel是ListBox/ItemsControl的默认设置,但如果您需要一些不同的布局,则始终可以覆盖ListBox.ItemsPanel模板

如果您可以遵循方法,则需要在ViewModel类中指定一个属性(在您的情况下,它将是索引),并且在列表框级别设置SortDescription将自动为您提供此功能。您不需要添加和删除实际的UIElements,只需添加/删除到ObservableCollection绑定到ListBox.ItemsSource即可。并指定适当的数据模板

如果您不熟悉CollectionViewSource,请选中此选项-

代码如下所示。。这很简单

   <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}}"/>


注意:

如果您为每个元素指定了特定的名称(即索引)。 删除此控件时,只需重命名结果控件即可


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

如果要排序,需要确保父控件为空,并且面板中的索引未被使用

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


使用Visual Tree Helper来断开或移动UIElement。

以上答案是正确的,但是如果您无法更改stackpanel(如果您没有足够的时间,或者编写了许多与stackpanel相关的代码),请尝试以下操作:

  • 将控件存储在列表或字典中
  • 对列表或字典排序
  • 使用以下命令从stackpanel中删除控件:stackpanel.Children.Remove(child)
  • 对于列表或字典的每个成员,使用StackPanel.Children.Insert(i,child)向StackPanel添加控件
    注意:代码正在运行,删除功能从StackPanel项(从树)中删除控件,但该控件已在内存中,因此该控件可以插入任何StackPanel或其相同项

    我可以…但当我尝试交换两个元素的位置时,仍然会得到相同的结果。我几乎可以使用任何容器……但我希望能够对它们进行重新排序,或者按照我指定的索引对它们进行排序。首先:使用ItemsControl,而不是ListBox:前者用于无法选择的内容列表@irco:从控件外部手动重新定位这样的元素并不容易,但如果您可以对源数据(而不是控件)进行重新排序,则可以获得相同的结果。Jobi的建议是正确的:CollectionView将根据您指定的索引自动对列表进行排序(即使您的列表是控件列表!)。我这样做,创建元素的数据来自db,问题是新元素可以随时显示在表上,我不能删除容器的集合,所以当我添加一个索引小于最后一个元素的新元素并将其添加到末尾时,需要进行排序。我要试试这个ItemsControl@JobiJoy我想我对wpf还不够熟悉,这是我第一个使用它的项目。我不确定StaticResource需要什么,因为创建userControls的数据来自数据库。如果您能为我指出正确的方向,我将不胜感激。请阅读本文,了解WPF开发的视图模型方法。您如何访问数据库?LINQ2SQL?你需要了解WPFN中的ObservableCollection、DataTemplate和ItemsControl的概念。没有更多的信息,只有索引,我需要向下或向上传输所有信息。如果我这样做,我不确定我是否完全理解你的意思……父项是StackPanel。子项集合,如果为空,我将丢失其中的其余元素,并且可能会使用索引,但这是排序的想法..将元素放置在其他元素所在的位置..同时stackPanel.Children.Insert会向下推这些元素