2010-03-03 16 views
7

Ho uno stackpanel con alcuni comandi utente aggiunti o rimossi durante il runtime. Questi elementi hanno un indice che gli assegno quando li nuovo, ho bisogno di mantenere questi elementi ordinati per quell'indice quindi prendo una funzione quicksort che li ordina in base all'indice ma sulla linea che fa lo scambioelementi di ordinamento in un pannello stack WPF

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

ottengo

"indice specificato è già in uso. Scollegare il bambino visivo in corrispondenza dell'indice specificato prima"

ho provato a copiarli in una variabile temporanea, eliminarli dalla raccolta e quindi assegnare li al loro indice giusto con la funzione Inserisci in UIElem entCollection, ma poi mi

"Specificato visiva è già un figlio di un altro visiva o la radice di un CompositionTarget"

C'è un elemento di clone che ho bisogno o qualcosa im manca da qualche parte?

risposta

11

Perché non utilizzare ListBox/ItemsSontrol e utilizzare CollectionViewSorce/SortDescription su di esso per eseguire questo lavoro. Aggiungere un elemento ai pannelli LayOut come stackpanel non è un modo efficace per andare nelle app WPF. StackPanel con orientamento verticale è l'impostazione predefinita per ListBox/ItemsControl, ma se volete un po 'diverso layout si può sempre ignorare ListBox.ItemsPanel Template

Se si riesce a seguire MVVM suddetto approccio, allora è una questione di specificare una proprietà (in il tuo caso sarà Index) nella tua classe ViewModel e impostare SortDescription a livello di listBox ti fornirà automaticamente questa funzionalità. Invece di aggiungere e rimuovere UIElement effettivi, è sufficiente aggiungere/rimuovere il binding ObservableCollection a ListBox.ItemsSource. E specificare il DataTemplate corretto.

Controllare questo se si arent familiarità con CollectionViewSource - http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.sortdescriptions.aspx

E il codice sarà più come seguito .. E 'abbastanza semplice.

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

nota: < --xmlns: scm = "CLR-namespace: System.ComponentModel; assemblaggio = WindowsBase" ->

+0

beh potrei ... ma questo produce comunque gli stessi risultati quando provo a scambiare le posizioni di due elementi. Uso praticamente qualsiasi contenitore ... ma voglio essere in grado di riordinarli o di ordinarli per l'indice che ho specificato – irco

+0

Primo: usare un ItemsControl, non un ListBox: il primo è per gli elenchi di cose che non sono intrinsecamente selezionabili. @irco: il riposizionamento manuale di elementi come questo dall'esterno di un controllo non è facilmente supportato nel modo in cui si sta tentando di farlo, ma se è possibile riordinare i dati di origine (anziché i controlli), si otterrà lo stesso risultato. Il suggerimento di Jobi è corretto: un CollectionView ordinerà automaticamente l'elenco in base all'indice specificato (anche se l'elenco è un elenco di controlli!). –

+0

Lo faccio, i dati per creare gli elementi provengono da un db, sono ordinati ... il problema è che i nuovi elementi possono apparire sul tavolo in qualsiasi momento e non posso semplicemente cancellare la raccolta del contenitore, quindi quando aggiungo un nuovo elemento con un indice più piccolo dell'ultimo elemento e il suo aggiunto alla fine, si presenta la necessità di ordinare. Proverò il ItemsControl – irco

0

se si dà ogni nome specifico elemento (che è indice). quando rimuovi questo controllo, puoi semplicemente rinominare i controlli dei risultati.

dopo che tutto il tuo controllo sarà ordinato.

+0

no ci sono molte più informazioni che solo l'indice, avrei bisogno di trasferire tutte le informazioni verso il basso o verso l'alto se l'ho fatto – irco

1

Se si desidera fare ciò è necessario assicurarsi che il Parent sia nullo e anche che l'indice nel pannello non sia in uso.

Se lo si cambia in una variabile temporanea, è sempre lo stesso riferimento.

Utilizzare l'albero di supporto di Visual Tree per scollegare o spostare UIElement.

+0

non sono sicuro di aver capito cosa intendi .... il genitore è la collezione StackPanel.Children, se è nullo perderò il resto degli elementi e l'indice potrebbe essere usato ma questa è l'idea dell'ordinamento ... inserendo elementi dove altri sono .. anche lo stackPanel.Children.Insert dovrebbe spingere gli elementi verso il basso – irco

4

La risposta di cui sopra è corretta, ma se non è possibile modificare lo StackPanel (se non avete abbastanza tempo, o hanno scritto molti codici relativi alla StackPanel) provate questo:

  1. Conservare i controlli in un lista o Dizionario
  2. ordinare l'elenco o dizionario
  3. rimuovere i controlli da StackPanel utilizzando: StackPanel.Children.Remove (bambino)
  4. Foreach membro della lista o dizionario aggiungere controlli a StackPanel utilizzando: StackPanel.Children.Insert (i , bambino);

nota: il codice funzioni, Rimuovi funzione rimuove il controllo dalla StackPanel elemento di (dall'albero) ma il controllo è già nella memoria in modo che il controllo è in grado di inserire in qualsiasi StackPanel o uguale di esso.

Problemi correlati