Sort items in a WPF stack

I have a stack panel with some user controls that are added or removed at runtime. These elements have an index, which I assign them when I new them, I need these elements to be sorted by this index, so I voted for the quicksort function, which sorts them by index but on a line that does swap

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

I get

"The specified index is already in use. First, disable the Visual child with the specified index"

I tried copying them to a temporary variable, removing them from the collection and then assigning them to my right index using the Insert function in the UIElementCollection, but then I get

"The specified visual is already a child of another Visual or CompositionTarget root"

Is there any clone element that I need or is there something missing?

+7
sorting c # wpf stackpanel
source share
4 answers

Why don't you use ListBox / ItemsSontrol and use CollectionViewSorce / SortDescription to do the job. Adding elements to a LayOut, such as a stackpanel, is not an efficient way to work in WPF applications. A vertically oriented stackpanel is the default for a ListBox / ItemsControl, but if you want some other layout, you can always override the ListBox.ItemsPanel template

If you can follow the MVVM apporach, then it is a matter of defining the property (in your case it will be Index) in your ViewModel class and setting SortDescription at the listBox level will automatically provide you this function. Instead of adding and removing the actual UIElements, you just need to add / remove the ObservableCollection binding to the ListBox.ItemsSource. And specify the correct DataTemplate.

Check this out if you are familiar with CollectionViewSource - http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.sortdescriptions.aspx

And the code will be more like below .. it's pretty simple.

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

note: <- XMLNS: SCM = "CLR names: System.ComponentModel; assembly = WindowsBase" β†’

+11
source share

The correct answer, but if you can’t change your stack panel (if you don’t have enough time or you have written a lot of codes related to the stack panel), try the following:

  • Save the controls in a list or dictionary
  • Sort list or dictionary
  • Remove controls from the stack pane using: StackPanel.Children.Remove (child)
  • A list item or dictionary adds controls to the StackPanel using: StackPanel.Children.Insert (i, child);

Note: the code works, the delete function removes the control from the StackPanel (from the tree), but the control is already in memory, so the control can be inserted into any StackPanel or its contents.

+4
source share

If you want to do this, you need to make sure that the parent element is null, and also that your index in the panel is not used.

If you just swap it with a temporary variable, it will still remain the same reference.

Use the visual tree helper to disable or move your UIElement.

+1
source share

if you specify the name of each element (which is an index). when you remove this control, you can simply rename the results controls.

After that, your entire control will be sorted.

0
source share

All Articles