сортировка элементов в стеке панели WPF - PullRequest
7 голосов
/ 03 марта 2010

У меня есть панель стека с некоторыми пользовательскими элементами управления, которые добавляются или удаляются во время выполнения. У этих элементов есть индекс, который я присваиваю им, когда я их создаю. Мне нужно сохранять эти элементы отсортированными по этому индексу, поэтому я использую функцию быстрой сортировки, которая сортирует их по индексу но на линии, которая делает обмен

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

Я получаю

"Указанный индекс уже используется. Сначала отключите дочерний элемент Visual по указанному индексу"

Я попытался скопировать их во временную переменную, удалить их из коллекции и затем присвоить им правильный индекс с помощью функции Вставить в UIElementCollection, но затем я получил

"Указанный визуал уже является дочерним элементом другого визуала или корнем цели CompositionTarget"

Есть ли какой-нибудь элемент клона, который мне нужен, или что-то где-то мне не хватает?

Ответы [ 4 ]

11 голосов
/ 03 марта 2010

Почему бы вам не использовать ListBox / ItemsSontrol и использовать CollectionViewSorce / SortDescription для этого, чтобы выполнить эту работу. Добавление элементов в панели LayOut, таких как stackpanel, не является эффективным способом использования приложений WPF. StackPanel с вертикальной ориентацией используется по умолчанию для ListBox / ItemsControl, но если вам нужен другой макет, вы всегда можете переопределить шаблон ListBox.ItemsPanel

Если вы можете следовать MVVM apporach, тогда нужно указать свойство (в вашем случае это будет Index ) в вашем классе ViewModel и установить SortDescription на уровне listBox автоматически предоставит вам эту функцию. Вместо того, чтобы добавлять и удалять фактические элементы UIE, вам просто нужно добавить / удалить привязку ObservableCollection к ListBox.ItemsSource. И укажите правильный 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-имена: System.ComponentModel; сборка = WindowsBase" ->

4 голосов
/ 19 августа 2011

Ответ выше верен, но если вы не можете изменить свою стековую панель (если у вас недостаточно времени или вы написали много кодов, связанных со стековой панелью), попробуйте следующее:

  1. Сохранить элементы управления в списке или словаре
  2. Сортировка списка или словаря
  3. Удалить элементы управления из стековой панели, используя: StackPanel.Children.Remove (child)
  4. Каждый элемент List или Dictionary добавляет элементы управления в StackPanel, используя: StackPanel.Children.Insert (i, child);

примечание: код работает, функция Remove удаляет элемент управления из элемента StackPanel (из дерева), но элемент управления уже находится в памяти, поэтому элемент управления может быть вставлен в любой элемент StackPanel или тот же элемент.

1 голос
/ 03 марта 2010

Если вы хотите сделать это, вам нужно убедиться, что родительский элемент имеет значение NULL, а также что ваш индекс на панели не используется.

Если вы просто поменяете его на временную переменную, это все та же ссылка.

Используйте Visual Tree Helper для отключения или перемещения вашего UIElement.

0 голосов
/ 03 марта 2010

, если вы даете каждому элементу конкретное имя (которое является индексом). когда вы удаляете этот элемент управления, вы можете просто переименовать элементы управления результатом.

после этого весь ваш контроль будет отсортирован.

...