Question

Je cherche à écrire un projet simple d'apprentissage WPF qui crée un ensemble de boutons dans une fenêtre principale redimensionnable. Il est l'un Button par entrée dans une collection, et le contenu de cette collection peut varier au cours de l'exécution. Je veux les boutons pour remplir toute la fenêtre (par exemple une touche @ largeur de 100%, 2 touches @ largeur de 50%, 3 boutons @ largeur de 33%, etc., le tout à hauteur de 100%). Une version simplifiée de ce jour ce que j'ai écrit est:

<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 en résulte ceci:

text alt

Je suis incapable de faire les boutons Étirer pour adapter la largeur et mes tentatives d'utiliser un Grid au lieu de StackPanel ont été vaines.

Alors, comme une amélioration facultative, je vous serais reconnaissant de suggestions sur la façon de le régler de telle sorte que s'il y a tellement de boutons qu'ils ne rentre pas correctement sur une ligne ou sont plus étroites que d'un seuil, il se terminera sur une nouvelle ligne ( la réduction de moitié de ce fait la hauteur des boutons si allant de 1 à 2 lignes).

Je voudrais souligner que je voudrais savoir comment faire le façon WPF . Je me rends compte que je peux consommer fenêtre redimensionne les messages et redimensionnez les contrôles explicitement, et comment je l'aurais fait avec MFC ou WinForms, mais de ce que j'ai lu ce n'est pas comment devrait se faire de telles choses avec WPF.

Était-ce utile?

La solution

Remplacer le panneau de commande de l'élément avec un UniformGrid, cette taille que tous les enfants, donc tout correspond exactement à:

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

Autres conseils

Je suis en mesure de construire sur la réponse de Nir pour remplir mon critère option permettant WPF gérés étirement avec plusieurs lignes.

D'abord, vous devez être en mesure de modifier les propriétés du modèle UniformGrid . Pour ce faire, vous devez stocker une référence. Il y a plusieurs méthodes pour accomplir cette . J'ai choisi de gérer les Loaded événement pour UniformGrid et stocker une référence à ce moment-là.

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

Et dans le code sous-jacent:

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

Ensuite, gérer les SizeChanged événement et régler le paramètre lignes selon tout critère que vous souhaitez.

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));
  }
}

Alors cela permet WPF de gérer l'étirement comme dans la réponse de Nir, mais vous permet d'ajuster explicitement le nombre de lignes. Le code ci-dessus donne ce résultat:

text alt

(exemple d'animation )


Mise à jour 2009/08/28:

J'ajustais ma demande d'apprentissage afin que le ItemsControl était dans un DataTemplate dans un ResourceDictionary séparé. Cependant, des événements tels que Loaded ne peuvent pas être traitées dans un fichier XAML ResourceDictionary externe, car il n'a pas de code-behind (en général). Par conséquent, je avais besoin de mettre en cache la référence au UniformGrid en utilisant une technique différente.

au lieu utilisé la méthode de FindItemsPanel d'Alan Haigh (10 réponses) . Tout d'abord, je l'ai remplacé le ItemsControl avec:

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

Alors dans mon ResourceDictionary, je mets le ItemsControl dans le DataTemplate:

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

Enfin, j'emmagasinés la référence au UniformGrid comme si basé sur un modèle:

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
}

Cela fonctionne exactement la même chose que ma solution précédente, mais sans nécessiter un gestionnaire d'événements dans le 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;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top