Frage

Ich versuche, ein einfaches WPF Lernprojekt zu schreiben, die eine Reihe von Schaltflächen in einem resizeable Hauptfenster erzeugt. Es gibt eine Button pro Eintrag in einer Sammlung sein, und der Inhalt dieser Sammlung während der Laufzeit kann variieren. Ich will die Tasten, um das gesamte Fenster (beispielsweise 1-Taste @ 100% Breite, 2 Tasten @ 50% Breite, 3 Tasten @ 33% Breite, etc. Alle auf 100% Höhe) zu füllen. Eine vereinfachte Version von dem, was ich geschrieben habe, so weit ist:

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

Daraus ergibt sich folgendermaßen aus:

alt text

Ich habe nicht in der Lage gewesen, die Tasten machen strecken die Breite und meine Versuche, passen ein Grid statt StackPanel waren ergebnislos zu verwenden.

Dann, als eine optionale Verbesserung, würde ich Vorschläge zu schätzen weiß, wie es so einstellen, dass, wenn es so viele Tasten sind, dass sie nicht richtig auf einer Linie passen oder schmaler sind als ein Schwellenwert ist, es auf eine neue Zeile umgebrochen wird ( wodurch die Taste Höhen zu halbieren, wenn 1 bis 2 Reihen zu gehen).

Ich möchte betonen, dass ich wissen möchte, wie dies die tun WPF Weg . Ich weiß, ich kann verbrauchen Fenster Meldungen der Größe und die Steuerelemente explizit die Größe, und das ist, wie ich es mit MFC oder WinForms getan haben würde, aber von dem, was ich gelesen habe, das ist nicht, wie solche Dinge sollen mit WPF erfolgen.

War es hilfreich?

Lösung

Ersetzen der Panels Artikel Steuerung mit einem Uniform, wird diese Größe alle Kinder so alles paßt genau:

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

Andere Tipps

ich in der Lage war, auf Nir Antwort zu bauen mein optional Kriterium zu erfüllen, so dass für WPF-Managed mit mehreren Reihen Stretching.

Zuerst müssen Sie in der Lage sein, die Eigenschaften der Vorlage Uniform zu ändern. Dazu müssen Sie einen Verweis auf sie speichern müssen. Es gibt mehrere Methoden zur Durchführung diese . Ich entschied mich für die Loaded Ereignis für die Uniform und speichern eine Referenz zu diesem Zeitpunkt zu behandeln.

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

Und in der Code-behind:

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

Dann behandeln Sie die Sizechanged Ereignis und stellen Sie die Zeilen Parameter nach, was auch immer Kriterien, die Sie wünschen.

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

So ermöglicht diese WPF das Strecken wie in Nir Antwort zu verwalten, sondern ermöglicht es Ihnen, explizit die Anzahl der Zeilen anpassen. Der obige Code gibt dieses Ergebnis:

alt text

(Animierte Probe hier )


Update 2009.08.28:

Ich hatte meine Einstellung Lernanwendung, so dass der ItemsControl in einem DataTemplate in einem separaten ResourceDictionary war. Allerdings Ereignisse wie Loaded nicht in einer externen ResourceDictionary XAML-Datei behandelt werden, da es keinen Code-Behind (in der Regel) hat. Daher musste ich den Verweis auf die UniformGrid mit einer anderen Technik cachen.

Ich benutzte stattdessen Alan Haighs FindItemsPanel Methode (10 antworten) . Zuerst habe ich ersetzt die ItemsControl mit:

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

Da ist in meinem ResourceDictionary, habe ich die ItemsControl im DataTemplate:

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

Schließlich habe ich den Verweis auf den Templat-UniformGrid als so gespeichert:

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
}

Dies ist nur das gleiche wie meine frühere Lösung funktioniert, aber ein Event-Handler in den ResourceDictionary ohne zu erfordern.

<!-- 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;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top