2010-03-03 121 views
7

我有一个在运行时期间添加或删除的一些用户控件的堆栈面板。 这些元素有一个索引,我分配给他们,当我新他们,我需要保持这些元素排序的索引,所以我wote快速排序函数,根据索引 排序他们,但在交换行堆栈面板中的排序元素WPF

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

我得到

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

我试着将它们复制到一个临时变量,从集合中删除它们,然后分配使用UIElem中的Insert函数将它们移动到它们的右侧索引entCollection,后来我找

“规定的目视已经是另一个Visual的孩子或CompositionTarget的根”

是否有我需要什么我在想念一个地方克隆元素?

回答

11

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

如果你能遵循MVVM apporach那么它是指定属性的问题(在你的情况它将索引)在您的ViewModel类和设置SortDescription在列表框级将自动给你这个功能。您不需要添加和删除实际的UIElements,只需要添加/删除ObservableCollection绑定到ListBox.ItemsSource。并指定适当的DataTemplate。

检查这一点,如果你的arent熟悉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-命名空间:System.ComponentModel程序;装配= WindowsBase” - >

+0

嗯,我可以......但是当我尝试交换两个元素的位置时,仍然会产生相同的结果。我几乎可以使用任何容器......但是我希望能够对它们重新排序,或者不必按照我指定的索引对它们排序 – irco 2010-03-03 17:26:44

+0

首先:使用ItemsControl而不是ListBox:前者用于列出事物不是固有的可选择的。 @irco:从控件外部手动重新定位像这样的元素并不容易以你想要的方式来支持,但如果你可以重新排序源数据(而不是控件),那么你就可以实现相同的结果。 Jobi的建议是正确的:一个CollectionView将根据您指定的索引自动对您的列表进行排序(即使您的列表是一个控件列表!)。 – 2010-03-03 18:00:30

+0

我这样做,创建元素的数据来自一个数据库,他们排序......问题是,新的元素可以随时出现在表上,我不能只是消灭容器的集合,所以当我添加索引小于最后一个元素的新元素,并将其添加到最后,就会出现排序需求。我会尝试ItemsControl – irco 2010-03-03 18:21:27

0

如果给每个元素的具体名称(它是索引)。当你删除这个控件时,你可以重命名结果控件。

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

+0

不存在更多的信息,只是索引,我需要将所有信息向下或向上传输,如果我这样做 – irco 2010-03-03 17:58:21

1

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

如果您只是将其交换为临时变量,它仍然是相同的参考。

使用可视树帮助器来疏散或移动您的UIElement。

+0

我不确定我完全明白你的意思....父母是StackPanel.Children集合,如果它是空的,我会失去其中的元素的其余部分,并且索引可能会被使用,但这就是排序..putting元素的想法,其他地方..另外stackPanel.Children.Insert应该将元素向下推 – irco 2010-03-03 18:03:27

4

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

  1. Store中的控制列表或字典
  2. 排序的列表或字典
  3. 从StackPanel中使用删除控件:StackPanel.Children.Remove(子)名单的
  4. FOREACH构件或字典使用添加控件的StackPanel:StackPanel.Children.Insert(ⅰ ,孩子);

注:该代码工作,删除函数从StackPanel的项目的(从树)的控制,但控制已经在内存中,以便控制能够在任何StackPanel中插入或相同的吧。