【问题标题】:sorting elements in a stackpanel WPF在堆栈面板 WPF 中对元素进行排序
【发布时间】:2011-01-23 07:40:57
【问题描述】:

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

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

我明白了

“指定索引已在使用中,先断开指定索引处的Visual子节点”

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

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

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

【问题讨论】:

    标签: c# wpf sorting stackpanel


    【解决方案1】:

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

    如果您可以遵循 MVVM 方法,那么只需在 ViewModel 类中指定一个属性(在您的情况下为 Index)并将 SortDescription 设置为listBox 级别将自动为您提供此功能。无需添加和删除实际的 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}}"/>
    

    注意:

    【讨论】:

    • 我可以...但是当我尝试交换两个元素的位置时仍然会产生相同的结果。我几乎使用任何容器......但我希望能够重新排序它们,或者不必按我指定的索引对它们进行排序
    • 首先:使用 ItemsControl,而不是 ListBox:前者用于列出本质上不可选择的事物。 @irco:在您尝试执行此操作的方式中,不容易支持从控件外部手动重新定位这样的元素,但是如果您可以重新排序源数据(而不是控件),那么您将实现相同结果。 Jobi 的建议是正确的:CollectionView 会根据您指定的索引自动对列表进行排序(即使您的列表是控件列表!)。
    • 我这样做了,创建元素的数据来自数据库,它们被排序..问题是新元素可以随时出现在桌子上,我不能只清除容器的集合,所以当我添加一个索引小于最后一个元素的新元素并将其添加到末尾时,需要进行排序。我会试试 ItemsControl
    • @JobiJoy 我想我对 wpf 还不够熟悉,这是我第一个使用它的项目。我不确定 StaticResource 需要什么,因为创建 userControls 的数据来自数据库。如果您能指出我正确的方向,我将不胜感激
    • 请阅读本文了解 WPF 开发的 View Model 方式。 msdn.microsoft.com/en-us/magazine/dd419663.aspx你是如何访问数据库的? LINQ2SQL? WPF中的ObservableCollection、DataTemplate和ItemsControl的思路你需要看
    【解决方案2】:

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

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

    【讨论】:

    • 不,除了索引之外还有很多信息,如果我这样做了,我需要将所有信息向下或向上传输
    【解决方案3】:

    如果您想这样做,您需要确保 Parent 为空,并且您的面板中的索引未在使用中。

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

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

    【讨论】:

    • 我不确定我是否完全明白你的意思....父级是 StackPanel.Children 集合,如果它为 null,我将丢失其中的其余元素,并且可能会使用索引,但这就是排序的想法..将元素放在其他地方..stackPanel.Children.Insert 应该将元素向下推
    【解决方案4】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-24
      • 2011-07-11
      • 2011-12-08
      • 1970-01-01
      • 2015-01-14
      • 2021-09-03
      相关资源
      最近更新 更多