我有一个stackpanel,其中包含一些在运行时添加或删除的用户控件。 这些元素有一个索引我分配给他们时,我需要保持这些元素按索引排序,所以我做了一个quicksort函数,根据索引对它们进行排序 但在进行交换的行
y = items[i]; //y is a temp variable
items[i] = items[j];
我得到了
“指定的索引已在使用中。首先断开指定索引处的Visual子项”
我尝试将它们复制到临时变量,从集合中删除它们然后使用UIElementCollection中的Insert函数将它们分配到它们的右侧索引,但后来我得到了
“指定的Visual已经是另一个Visual的子项或CompositionTarget的根”
我需要克隆元素或某些东西在某处丢失吗?
答案 0 :(得分:11)
为什么不使用ListBox / ItemsSontrol并使用CollectionViewSorce / SortDescription来完成这项工作。将元素添加到LayOut面板(如stackpanel)不是一种有效的WPF应用程序。具有垂直方向的StackPanel是ListBox / ItemsControl的默认设置,但是如果您想要一些不同的布局,则可以始终覆盖ListBox.ItemsPanel模板
如果您可以关注 MVVM apporach,则需要在ViewModel类中指定属性(在您的情况下,它将 Index )并设置listBox级别的SortDescription将自动为您提供此功能。您只需添加/删除ObservableCollection绑定到ListBox.ItemsSource,而不是添加和删除实际的UIElements。并指定正确的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}}"/>
注意:&lt; - 的xmlns:SCM = “CLR-命名空间:System.ComponentModel程序;装配= WindowsBase” - &GT;
答案 1 :(得分:4)
上面的答案是正确的,但是如果你不能改变你的堆叠面板(如果你没有足够的时间,或者写了很多与堆叠面板相关的代码),试试这个:
注意:代码正常工作,Remove函数从StackPanel项目(从树中)删除控件,但控件已经在内存中,因此控件可以插入任何StackPanel或其中。
答案 2 :(得分:1)
如果你想这样做,你需要确保Parent为null,并且你的面板中的索引没有被使用。
如果你只是将它换成临时变量,它仍然是相同的参考。
使用Visual Tree Helper来取消或移动您的UIElement。
答案 3 :(得分:0)
如果给每个元素指定特定名称(即索引)。 删除此控件时,您只需重命名结果控件。
之后,您的所有控件都将被排序。