2015-03-11 23 views
5

È possibile regolare la larghezza di tutti i TextBlocks in WrapPanel alla dimensione del TextBlock più grande all'interno di WrapPanel? Il risultato finale dovrebbe essere che la larghezza del controllo contenente "Alcuni dati" abbia la stessa larghezza del controllo contenente "Ancora più dati di prima". Ho allegato al mio codice iniziale come punto di partenza. Ho usato le stringhe come esempio, ma i dati e il modello di raccolta potrebbero essere qualsiasi cosa, quindi non posso fare affidamento sulla lunghezza della stringa.WPF: Sincronizza la larghezza di tutti gli articoli in ItemsControl

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <Collections:ArrayList x:Key="data"> 
      <System:String>Some data</System:String> 
      <System:String>Some more data</System:String> 
      <System:String>Even more data than before</System:String> 
     </Collections:ArrayList> 
    </Window.Resources> 
    <ItemsControl ItemsSource="{StaticResource data}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel></WrapPanel> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Border Margin="5" BorderThickness="1" BorderBrush="Black"> 
        <TextBlock Text="{Binding}"></TextBlock> 
       </Border> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Window> 

E un'immagine del output desiderato:

Desired output

risposta

10

impiego di una griglia di formato comune:

<ItemsControl ItemsSource="{StaticResource data}" Grid.IsSharedSizeScope="True"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel></WrapPanel> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto" SharedSizeGroup="ColumnSize" /> 
       </Grid.ColumnDefinitions> 
       <Border Margin="5" BorderThickness="1" BorderBrush="Black"> 
        <TextBlock Text="{Binding}"></TextBlock> 
       </Border> 
      </Grid> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

Tutte le colonne sono garantiti per essere la stessa larghezza condividono un gruppo di dimensioni. Poiché vengono ridimensionate automaticamente, verranno ridimensionate anche all'istanza più grande di qualsiasi contenuto della griglia.

+0

Piuttosto una soluzione elegante. Questo risolve il mio problema immediato abbastanza bene senza dover scrivere alcun codice personalizzato. Ci sono dei limiti che vengono immediatamente in mente riguardo a questa risposta? – mortalapeman

4

Si deve creare la propria versione personalizzata di un WrapPanel che è derivata da WrapPanel per ottenere ciò che si desidera. Normalmente per un pannello personalizzato è necessario eseguire l'override seguenti 2 metodi:

  • MeasureOverride
  • ArrangeOverride

Nel tuo caso è necessario measueoverride dove si iterare gli elementi e scoprire quale è il più grande e quindi utilizzare la stessa dimensione per tutti gli elementi in arrangiamento.

qualche informazione in più su come creare un pannello personalizzato: http://www.wpftutorial.net/CustomLayoutPanel.html

+0

Un pannello personalizzato con le caratteristiche leggermente modificate del pannello di avvolgimento era quello che pensavo avrei dovuto accontentarmi, ma questo è fino a quando ho visto la risposta @TobyCrawford ha proposto. – mortalapeman

2

È possibile aggiungere HorizontalContentAlignment = Stretch e Aggiungi UniformGrid in ItemsPanel.

<Window.Resources> 
    <Collections:ArrayList x:Key="data"> 
     <System:String>Some data</System:String> 
     <System:String>Some more data</System:String> 
     <System:String>Even more data than before</System:String> 
    </Collections:ArrayList> 
</Window.Resources> 
<ListBox ItemsSource="{StaticResource data}" HorizontalContentAlignment="Stretch"> 
    <ListBox.ItemsPanel> 
     <ItemsPanelTemplate> 
      <UniformGrid IsItemsHost="True"></UniformGrid> 
     </ItemsPanelTemplate> 
    </ListBox.ItemsPanel> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <Border Margin="5" BorderThickness="1" BorderBrush="Black" > 
       <TextBlock Text="{Binding}" Width="{Binding 
      RelativeSource={RelativeSource TemplatedParent}, 
      Path=Width}"></TextBlock> 
      </Border> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 
+0

UniformGrid, la soluzione a più problemi di quanto ci si aspetterebbe. – Will

+0

IMHO non soddisfa i requisiti dell'OP. Cosa succede se si ridimensiona la finestra? –

+0

Non conoscevo UniformGrid fino a questo post, grazie per quello. Sfortunatamente, devo concordare con @PhilipStuyck nel fatto che questo non ha le stesse caratteristiche di ridimensionamento del pannello di wrap. – mortalapeman

1

Questa è un'alternativa al pannello suggerimento personalizzato di Philip Stuyck che si possono trovare più semplice per il particolare scenario. (È un po 'un trucco, ammettiamolo.)

È possibile calcolare la lunghezza di una stringa utilizzando la classe FormattedText. Quindi puoi scorrere le tue stringhe e calcolare la lunghezza massima (questo presuppone anche che tu conosca la famiglia e la dimensione del font). Quindi lega la larghezza dei blocchi di testo alla larghezza massima. Vorrei memorizzare il valore della larghezza in una singola proprietà a livello di genitore, quindi utilizzando un RelativeSource vincolante:

<TextBlock Text="{Binding}" 
      Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, 
          Path=MaximumWidth}}" 
     /> 

(Uno svantaggio di questo approccio è che se i cambiamenti voci di raccolta, si dovrà ricalcolare MaximumWidth.)

+0

Purtroppo, non riesco a calcolare la lunghezza della stringa poiché il mio vero problema non ha nulla a che fare con le stringhe, le usavo solo come esempio. Avevo preso in considerazione una sorta di legatura della larghezza ancestrale, ma speravo in una soluzione più elegante. Tuttavia, è comunque bello sapere che si può fare in questo modo. – mortalapeman

Problemi correlati