Wie verwende ich DockStyle.Fill für Standardsteuerelemente in WPF?

92

Ich verwende Windows-Formulare, um ein Bedienfeld zu erstellen, Steuerelemente darin zu platzieren und sie so DockStyle.Fillzu gestalten, dass ihre Größe für das umgebende Bedienfeld maximal ist.

In WPF möchte ich das gleiche haben. Ich habe ein TabControl und möchte, dass seine Größe so viel wie möglich vom Formular ausfüllt. Ich habe ein Menübandsteuerelement (RibbonControlsLibrary) und möchte, dass der Rest des Formulars mit dem TabControl in maximaler Größe ausgefüllt wird.

(Ich möchte keine Steuerelemente wie das Andocken in Visual Studio andocken, sondern nur alte Docking-Mechanismen.)

Citronas
quelle

Antworten:

182

Das WPF-Äquivalent von WinForms 'DockStyle.Fill lautet:

HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Dies ist die Standardeinstellung für fast Steuerelemente. Sie müssen also im Allgemeinen überhaupt nichts tun, damit ein WPF-Steuerelement seinen übergeordneten Container füllt : Dies geschieht automatisch. Dies gilt für alle Container, die ihre Kinder nicht auf die Mindestgröße drücken.

Häufige Fehler

Ich werde nun einige häufige Fehler erklären, die verhindern, dass HorizontalAlignment="Stretch" VerticalAlignment="Stretch"sie wie erwartet funktionieren.

1. Explizite Höhe oder Breite

Ein häufiger Fehler besteht darin, eine Breite oder Höhe für ein Steuerelement explizit anzugeben. Also, wenn Sie dies haben:

<Grid>
  <Button Content="Why am I not filling the window?" Width="200" Height="20" />
  ...
</Grid>

Entfernen Sie einfach die Attribute Breite und Höhe:

<Grid>
  <Button Content="Ahhh... problem solved" />
  ...
</Grid>

2. Das Bedienfeld drückt die Steuerung auf die Mindestgröße

Ein weiterer häufiger Fehler besteht darin, dass das enthaltene Bedienfeld Ihre Steuerung so fest wie möglich drückt. Zum Beispiel drückt ein vertikales StackPanel seinen Inhalt immer vertikal so klein wie möglich:

<StackPanel>
  <Button Content="Why am I squished flat?" />
</StackPanel>

Wechseln Sie zu einem anderen Panel und Sie können loslegen:

<DockPanel>
  <Button Content="I am no longer squished." />
</DockPanel>

Außerdem wird jede Rasterzeile oder -spalte mit der Höhe "Auto" auf ähnliche Weise ihren Inhalt in diese Richtung drücken.

Einige Beispiele für Behälter, die ihre Kinder nicht quetschen, sind:

  • ContentControls quetschen niemals ihre Kinder (dazu gehören Border, Button, CheckBox, ScrollViewer und viele andere).
  • Raster mit einer einzelnen Zeile und Spalte
  • Raster mit Zeilen und Spalten der Größe "*"
  • DockPanel drückt sein letztes Kind nicht zusammen
  • TabControl drückt seinen Inhalt nicht zusammen

Einige Beispiele für Behälter, die ihre Kinder quetschen, sind:

  • StackPanel drückt in seiner Ausrichtungsrichtung
  • Das Raster mit einer Zeile oder Spalte in der Größe "Auto" wird in diese Richtung gedrückt
  • DockPanel drückt alle bis auf das letzte Kind in ihre Dockrichtung
  • TabControl drückt seinen Header (was auf der Registerkarte angezeigt wird)

3. Explizite Höhe oder Breite weiter außen

Es ist erstaunlich, wie oft ich Grid oder DockPanel mit einer expliziten Höhe und Breite sehe, wie folgt:

<Grid Width="200" Height="100">
  <Button Content="I am unnecessarily constrainted by my containing panel" />
</Grid>

Im Allgemeinen möchten Sie keinem Panel eine explizite Höhe oder Breite zuweisen. Mein erster Schritt bei der Diagnose von Layoutproblemen besteht darin, jede explizite Höhe oder Breite zu entfernen, die ich finden kann.

4. Das Fenster ist SizeToContent, wenn es nicht sein sollte

Wenn Sie SizeToContent verwenden, wird Ihr Inhalt auf die Mindestgröße komprimiert. In vielen Anwendungen ist dies sehr nützlich und die richtige Wahl. Wenn Ihr Inhalt jedoch keine "natürliche" Größe hat, sollten Sie SizeToContent wahrscheinlich weglassen.

Ray Burns
quelle
Ich habe hier eine ziemlich komplexe neue Frage zum Layout hinterlassen . Nachdem Sie Ihre Antwort hier gelesen haben, denken Sie, dass Sie es herausfinden können. Prost
Berryl
7
Hervorragende Antwort! Ich wünschte, ich könnte dir irgendwie Bonuspunkte geben. :)
Jim Raden
@ Jim Raden: Sie können dieser Frage ein Kopfgeld hinzufügen und die Punkte Ray Burns zuweisen;)
Citronas
1
Randnotiz für zukünftige Leser: Es wird erst in der Entwurfsansicht aktualisiert, wenn Sie es neu kompilieren.
David
"<Button Content =" Warum fülle ich das Fenster nicht aus? "Width =" 200 "Height =" 20 "/>" hat mich verrückt gemacht! XD
Jack Frost
7

Sie können tun, was Sie wollen, indem Sie einfach sagen DockPanel LastChildFill="True"und dann sicherstellen, dass das, was Sie als Füllstoff haben möchten, tatsächlich das letzte Kind ist!

Das Raster ist das Biest eines Layouts, mit dem Sie fast alles machen können, aber das DockPanel ist normalerweise die richtige Wahl für Ihr äußerstes Layoutfenster. Hier ist ein Pseudocode-Beispiel:

<DockPanel LastChildFill="True">
    <MyMenuBar DockPanel.Dock="Top"/>
    <MyStatus DockPanel.Dock="Bottom"/>

    <MyFillingTabControl />
</DockPanel>
Berryl
quelle
5

Wickeln Sie Ihre Steuerelemente einfach in ein Raster mit zwei Zeilen. Das Raster verwendet automatisch den gesamten ihm zugewiesenen Platz und Sie können die Zeilen so definieren, dass sie den gesamten verbleibenden Platz einnehmen, indem Sie ihnen eine Höhe von "*" geben. Die erste Zeile in meinem Beispiel (Höhe = "Auto") nimmt so viel Platz ein, wie das Menüband benötigt. Hoffentlich hilft das.

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Ribbon Grid.Row="0" />

  <TabPage Grid.Row="1" />
</Grid>

Durch Hinzufügen des Attributs "Grid.Row = .." zu untergeordneten Steuerelementen des Rasters werden diese Zeilen des Rasters zugewiesen. Dann passt das Raster die Größe der untergeordneten Elemente an, wie in den Zeilendefinitionen definiert.

andyp
quelle
Geht in die richtige Richtung, danke. Ich habe es geschafft, das Raster einzufügen, aber jetzt muss ich dem TabControl mitteilen, dass es die gesamte noch verfügbare Größe verwenden soll. Wie kann ich das erreichen?
Citronas
Sie müssen das Attribut "Grid.Row" für das TabControl hinzufügen und der entsprechenden Zeilendefinition eine Höhe von "*" geben - wie im Beispiel gezeigt.
Andyp
0

Ich habe hier viele Methoden ausprobiert, kann aber mein Problem nicht lösen. (Füllen Sie andere Kontrolle in Kontrolle)

Bis ich es gefunden habe

<Name_Control Height="auto" Width="auto"/>
//default
//HorizontalAlignment="Stretch" 
//VerticalAlignment="Stretch"

Beispiel:

//UserControl:
<UserControl Name="UC_Test" Height="auto" Width="auto" />
//Grid: 
<Grid Name="Grid_test" Grid.ColumnSpan="2" Grid.Row="2" />
//Code: 
Grid_test.Children.Add(UC_Test);

Für einfaches Design

<UserControl Name="UC_Test" Height="100" Width="100" />
//Code
Grid_test.Children.Add(UC_Test);
UC_Test.Width = Double.NaN;
UC_Test.Height = Double.NaN;
Trương Quốc Khánh
quelle