Domanda

Sto tentando di scrivere un semplice progetto di apprendimento WPF che crea una serie di pulsanti all'interno di una finestra principale ridimensionabile. Ci deve essere uno Button per ogni voce in una collezione, e il contenuto di tale raccolta può variare in fase di esecuzione. Voglio i pulsanti per riempire l'intera finestra (larghezza per esempio 1 pulsante @ 100%, 2 tasti @ larghezza 50%, 3 pulsanti @ larghezza 33%, ecc tutti al 100% altezza). Una versione semplificata di quello che ho scritto finora è:

<ItemsControl x:Name="itemscontrolButtons" ItemsSource="{Binding}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Tag="{Binding}">
        <TextBlock Text="{Binding}" />
      </Button>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>
...    
List<string> listButtonTexts = new List<string>() { "Button1", "Button2" };
...
itemscontrolButtons.DataContext = listButtonTexts;

Il risultato è questo:

alt text

Sono stato in grado di rendere i pulsanti si estendono in base alla larghezza ed i miei tentativi di usare un Grid invece di StackPanel erano inutili.

Poi, come un miglioramento optional, apprezzerei suggerimenti su come regolarlo in modo tale che se ci sono così tanti pulsanti che non possono adattano correttamente su una linea o che sono più stretto di una soglia, si avvolgono su una nuova linea ( dimezzando così i pulsanti altezze se vanno da 1 a 2 righe).

mi piacerebbe sottolineare che mi piacerebbe sapere come fare questo il modo WPF . Mi rendo conto che posso consumare finestra ridimensionare i messaggi e ridimensionare i controlli in modo esplicito, ed è così che avrei fatto con MFC o WinForms, ma da quello che ho letto che non è come queste cose dovrebbero essere fatte con WPF.

È stato utile?

Soluzione

Sostituire il pannello di controllo della voce con un UniformGrid, questa dimensione volontà tutti i bambini in modo tutto si adatta esattamente:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Rows="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

Altri suggerimenti

Sono stato in grado di costruire su risposta di Nir per compiere il mio criterio facoltativo che consente la WPF gestiti estende con più righe.

Per prima cosa è necessario essere in grado di alterare le proprietà del modello UniformGrid . Per fare ciò è necessario memorizzare un riferimento ad esso. Ci sono diversi metodi per realizzare questo . Ho scelto di gestire il Loaded evento per il UniformGrid e memorizzare un riferimento a quel tempo.

<ItemsControl ItemsSource="{Binding}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid Rows="1" Loaded="UniformGrid_Loaded" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>

E nel codice dietro:

UniformGrid uniformgridButtons;
private void UniformGrid_Loaded(object sender, RoutedEventArgs e)
{
  uniformgridButtons = sender as UniformGrid;
}

Quindi, gestire il SizeChanged eventi e regolare il parametro file in base a qualsiasi criterio che si desidera.

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
  if ((uniformgridButtons != null) && (this.Width > 0))
  {
    // Set row count according to your requirements
    uniformgridButtons.Rows = (int)(1 + ((this.MinWidth * iButtonCount) / this.Width));
  }
}

Quindi questo permette WPF di gestire l'allungamento come nella risposta di Nir, ma consente di regolare in modo esplicito il numero di righe. Il codice di cui sopra dà questo risultato:

alt text

(Animated campione qui )


Aggiornamento 2009/08/28:

I stava sistemando la mia domanda di apprendimento in modo che il ItemsControl era in un DataTemplate in un ResourceDictionary separata. Tuttavia, eventi come Loaded non possono essere trattati in un file XAML ResourceDictionary esterno perché non ha code-behind (di solito). Pertanto, avevo bisogno di memorizzare nella cache il riferimento al UniformGrid utilizzando una tecnica diversa.

Ho invece usato metodo FindItemsPanel di Alan Haigh (10 ° risposta) . In primo luogo, ho sostituito il ItemsControl con:

<ContentPresenter x:Name="contentpresenterButtons" Content="{Binding obscolButtons}" />

Poi nel mio ResourceDictionary, ho messo il ItemsControl nella DataTemplate:

<DataTemplate DataType="{x:Type local:Buttons}">
  <ItemsControl ... 
</DataTemplate>

Infine, ho memorizzato il riferimento alla UniformGrid su modelli come:

private void Window_Loaded(object sender, RoutedEventArgs e) {
  uniformgridButtons = FindItemsPanel<UniformGrid>(contentpresenterButtons);
  // Also call the code in Window_SizeChanged which I put in another method
}

Questo funziona proprio come la mia soluzione precedente, ma senza la necessità di un gestore di eventi nel ResourceDictionary.

<!-- width must be explicitly set for this example -->
<StackPanel 
    Name="MyStack" 
    Orientation="Horizontal"
    Width="250"
    Load="Window_Loaded"> 
    <Button/>
    <Button/>
    <Button/>
</StackPanel>

public void Window_Loaded(object sender, RoutedEventArgs e)
{
    UIElementCollection elements = MyStack.Children;
    int count = elements.Count;

    foreach (UIElement element in elements)
    {
        if (element is Button)
            ((Button)element).Width = MyStack.Width / count;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top