2012-07-05 7 views
13

Ho bisogno di elencare gli elementi (tutti della stessa dimensione) verticalmente (con un ScrollViewer). Voglio che le voci di diffondersi attraverso x colonne se il contenitore è abbastanza grande per visualizzare x colonneElenca elementi verticalmente su un WrapPanel e sfrutta più colonne

prima ho provato che:

<ScrollViewer> 
    <toolkit:WrapPanel Orientation="Horizontal" ItemHeight="30" ItemWidth="100"> 
     <Button Content="1" /> 
     <Button Content="2" /> 
     <Button Content="3" /> 
     <Button Content="4" /> 
     <Button Content="5" /> 
    </toolkit:WrapPanel> 
</ScrollViewer> 

Risultato - Il WrapPanel funziona come voglio ma i miei articoli sono ordinati da "Da sinistra a destra" (non verticalmente

poi ho cercato di Seet l'orientamento della WrapPanel a "verticale":

Risultato - I miei oggetti sono ordinate in senso verticale ma non spalmato su più colonne.

Ecco come mi piacerebbe elementi che devono essere rese:

Mi piacerebbe davvero evitare di dover scrivere codice monitorare la dimensione di controllo per creare/rimuovere colonne seconda delle sue dimensioni.

risposta

9

Se si imposta Orientation su Vertical, è inoltre necessario impostare l'altezza di rendering. Ad esempio a WrapPanel, Height="150".

+0

voglio l'altezza del WrapPanel essere dinamico per prendere lo spazio verticale di cui ha bisogno per visualizzare gli elementi in 2 colonne (o 3, o 4, ecc. a seconda della larghezza del controllo) – danbord

+0

@danbord, non funziona così. Il 'WrapPanel'sarà verticalmente tutti gli elementi che si adattano alla prima colonna e tutti gli elementi si sposteranno alla colonna successiva. Nel tuo caso il 'WrapPanel' posizionerà tutti gli elementi in una colonna perché c'è una limitazione all'altezza. – Zabavsky

1

L'unico modo per eseguire questa operazione con WrapPanel è impostare esplicitamente Height.

Sembra che si desidera che gli elementi siano distribuiti uniformemente sulle colonne con la colonna sinistra che ha al massimo un elemento in più rispetto alla colonna a destra. Se questo è ciò che stai cercando, dovrai creare il tuo pannello personalizzato. Dai un'occhiata a this per vedere come iniziare. Avrai bisogno di una proprietà di dipendenza ItemWidth e ItemHeight e calcoli il numero di colonne che puoi ottenere usando ItemWidth e la larghezza disponibile.

2

Questo tipo di comportamento non è possibile con un WrapPanel senza definire la sua Height

Un'alternativa è possibile utilizzare è un Grid, dove nel OnLoaded e OnSizeChanged, calcola quante colonne si adatta, quindi imposta la riga/Definizioni di colonna di Grid e Grid.Row/Grid.Column di ciascun oggetto nel code-behind. Non è bello, ma dovrebbe essere abbastanza semplice da mettere insieme e funzionerà.

L'altra opzione creerebbe il proprio pannello personalizzato che organizza gli elementi come desiderato. Potresti anche essere in grado di trovare qualcosa disponibile online che lo fa già

3

Finalmente qualcosa che funziona ma ha bisogno di codice. Sono d'accordo con tutti voi quando affermate che dobbiamo ridimensionare l'altezza del WrapPanel per farlo funzionare.Qui è la mia soluzione:

<ScrollViewer x:Name="scroll1" SizeChanged="ScrollViewer_SizeChanged" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> 
    <toolkit:WrapPanel x:Name="wp1" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Left" ItemHeight="30" ItemWidth="250" > 
     <Button Content="1" /> 
     <Button Content="2" /> 
     <Button Content="3" /> 
     <Button Content="4" /> 
     <Button Content="5" /> 
     <Button Content="6" /> 
     <Button Content="7" /> 
     <Button Content="8" /> 
    </toolkit:WrapPanel> 
</ScrollViewer> 

Ecco il CodeBehind:

private void ScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    // Stupid magical number because ViewPortHeight is sometimes not accurate 
    Double MAGICALNUMBER = 2; 

    // Ensure ViewPortSize is not 0 
    if (scroll1.ViewportWidth <= MAGICALNUMBER || scroll1.ViewportHeight <= MAGICALNUMBER) 
     return; 

    Size contentSize = new Size(scroll1.ViewportWidth - MAGICALNUMBER, scroll1.ViewportHeight - MAGICALNUMBER); 
    Size itemSize = new Size(wp1.ItemWidth, wp1.ItemHeight); 

    Size newSize = CalculateSizeBasedOnContent(contentSize, wp1.Children.Count, itemSize); 

    wp1.Width = newSize.Width; 
    wp1.Height = newSize.Height; 
} 


private Size CalculateSizeBasedOnContent(Size containerSize, int itemsCount, Size itemSize) 
{ 

    int iPossibleColumns = (int)Math.Floor(containerSize.Width/itemSize.Width); 
    int iPossibleRows = (int)Math.Floor(containerSize.Height/itemSize.Height); 

    // If all items can fit in first column without scrolling (or if container is narrow than the itemWidth) 
    if (itemsCount <= iPossibleRows || containerSize.Width < itemSize.Width) 
    return new Size(itemSize.Width, (itemsCount * itemSize.Height)); 

    // If all items can fit in columns without scrollbar 
    if (iPossibleColumns * iPossibleRows > itemsCount) 
    { 
    int columnsNeededForDisplay = (int)Math.Ceiling((itemsCount/(Double) iPossibleRows)); 
    return new Size(columnsNeededForDisplay * itemSize.Width, containerSize.Height); 
    } 

    // Here scrolling is needed even after spreading in columns 
    int itemsPerColumn = (int)Math.Ceiling(wp1.Children.Count/(Double)iPossibleColumns); 
    return new Size(containerSize.Width, itemsPerColumn * itemSize.Height); 

} 
+0

Recentemente stavo scherzando con 'ScrollViewer.ViewportHeight' ... forse la parte inferiore di [questa risposta] (http://stackoverflow.com/a/11157916/302677) potrebbe aiutarti? – Rachel

+0

+1: Questo ha funzionato benissimo con alcune modifiche molto minori. Grazie per la soluzione! :) – reSPAWNed

+2

Solo una FYI: se si sta utilizzando un oggetto ItemsControl al posto di un WrapPanel e si modifica in modo dinamico l'oggetto ItemsSource, questo non verrà seguito finché non si ridimensiona la finestra. Ho funzionato usando l'evento LayoutUpdated piuttosto che l'evento SizeChanged, che verrà chiamato più spesso, ma come si può leggere su MSDN è preferibile quando si scherza con il layout. – reSPAWNed

Problemi correlati