Controls in WPF dynamisch vergrößern
-
Nehmen wir an es gibt ein MainWindow mit Textboxen, Buttons, etc tief in der Hierarchieebene der Container. Wenn der User das Fenster verbreitert, dann sollen die Textboxen proportional auch an Breite gewinnen. Die Buttons sollen sich nicht verbreitern, jedoch wenn ich das in Kauf nehmen muß, dann sei es eben so.
Welche Container Elemente würdet ihr verwenden und welche Eigenschaften würdet ihr setzen um dieses Verhalten zu erreichen?
-
Vermutlich einfach ein Grid.
Ist aber irgendwie schwer zu sagen wenn man nicht weiss was "tief in der Hierarchie" heisst.
Notfalls kann man z.B. auch so eine lustige Data-Binding Formel als Breite eines Elements angeben, die dann anhand der Fenstergrösse halt die gewünschte Breite ausrechnet.
-
Peeker schrieb:
Nehmen wir an es gibt ein MainWindow mit Textboxen, Buttons, etc tief in der Hierarchieebene der Container.
Auch ich habe ein Problem mit dem "tief in der Hierarchie", ich nehme mal an das du etwas wie UserControls etc. einbettest.
Peeker schrieb:
Wenn der User das Fenster verbreitert, dann sollen die Textboxen proportional auch an Breite gewinnen. Die Buttons sollen sich nicht verbreitern, jedoch wenn ich das in Kauf nehmen muß, dann sei es eben so.
Sofern das Fenster im ganzen zusammengesetzt wird, stellt das mit einem Grid kein Problem dar (ggf. auch Kombiniert mit anderen Containern, dazu unten mehr). Falls wiederum noch zusammengesetzte UserControls hinzu kommt, hängt es von deren Aufbau ab, ob ggf. noch weitere Bindings dazu kommen müssen.
Grundsätzlich arbeite ich zumeist bei einem solchen Aufbau mit Grids deren Spalten proportional wachsen (ggf. mit ein paar Spalten mit festen breiten dazwischen, da ich Abstände zwischen den Controls über das gesamte Fenster möglichst an gleichen Stellen haben will (und nicht bei allen Margins etc. setzen möchte). In der Regel befinden sich bei uns die Buttons immer unten in zwei StackPanel (eines Links, eines Rechts ausgerichtet - allgemeine Buttons wie Speichern/Abbrechen/Schließen... sind bei uns immer rechts, speziell auf Datensätze, Listenelemente etc. ausgerichtete immer links.
-
Vorher habe ich mit Windows Forms gearbeitet und im Resize Ereignis mit viel Rechnerei die Controls verschoben und die Größe angepasst. Mir wurde von einem Kollegen WPF verkauft: Diese häßliche Rechnerei muß du jetzt nicht mehr machen, klick dir einfach die Oberfläche zusammen und WPF macht das dann.
So wie ich das sehe kriege ich statt der Rechnerei eine tief geschachtelten XML Code. Beispiel: Ich möchte einen Kunden abbilden. Ich erstelle ein Label und eine Tetxbox und packe beides zB in ein Dockpanel, nun habe ich den Vornamen abgebildet. Gleiches mache ich für Nachname, Adresse, etc. Nun packe ich die Dockpanels in ein übergeordnetes Dockpanel, nun habe die Person abgebildet. Daneben erstelle ich ein Dockpanel in das ich Daten zum Kundenequipment eintrage. Wenn ich nun Kundenequipment und Person in ein übergeordnetes Dockpanel zusammenlege, dann habe ich endlich den Kunden abgebildet. Daher die Hierarchie.
Problem: Wenn ich das MainWindow Resize, vergößern oder verkleinern sich nicht gleichmäßig die Kinderlemente.Als Anfänger hätte ich gedacht das man sich die Beispiel Gui so zusammenklicken kann:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="420"> <DockPanel Name="Kunde" Margin="4"> <DockPanel Name="Person" DockPanel.Dock="Left"> <DockPanel DockPanel.Dock="Top"> <Label Content="Vorname" DockPanel.Dock="Top"/> <TextBox Text="Max" DockPanel.Dock="Top"/> </DockPanel> <DockPanel DockPanel.Dock="Top"> <Label Content="Nachname" DockPanel.Dock="Top"/> <TextBox Text="Murks" DockPanel.Dock="Top"/> </DockPanel> </DockPanel> <DockPanel Name="Kundenequipment" DockPanel.Dock="Left" Margin="4"> <Label Content="Kundenequipment" DockPanel.Dock="Top"/> <ListBox /> </DockPanel> </DockPanel> </Window>
Ihr sagt dazu nimmt man einen Grid. Ich habe mich mal versucht:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="420"> <Grid Name="Kunde" Margin="4"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Label Grid.Column="0" Grid.Row="0" Content="Vorname:" Margin="4,0,4,0"/> <TextBox Grid.Column="0" Grid.Row="1" Text="Max" TextWrapping="Wrap" Margin="4,0,4,0"/> <Label Grid.Column="0" Grid.Row="2" Content="Produkt:" Margin="4,0,4,0"/> <TextBox Grid.Column="0" Grid.Row="3" Text="Murks" TextWrapping="Wrap" Margin="4,0,4,0"/> <ListBox Grid.Column="1" Grid.Row="0" Grid.RowSpan="4"/> </Grid> </Window>
Das ist im Grunde das Verhalten das ich haben wollte.
Das heißt also wenn ich meine Fenster mit einem solchem Auto-Resize austatten will, dann kann ich Dockpanel, Stackpanel, etc alle links liegen lassen, weil die nur für Fenster zu gebrauchen sind die nicht die Größe verändern? Bei den Forms also rumrechnen, bei WPF das Fenster in einen Grid einteilen und da irgendwie rumschubbern?
-
abcd schrieb:
Das heißt also wenn ich meine Fenster mit einem solchem Auto-Resize austatten will, dann kann ich Dockpanel, Stackpanel, etc alle links liegen lassen, weil die nur für Fenster zu gebrauchen sind die nicht die Größe verändern?
Falsch. Dockpanel, Stackpanel und Co sind auch bei Fenstern sinnvoll die, die Größe verändern - doch ihre Aufgaben sind andere als die beim Grid. Eine Größenänderung heißt nicht automatisch das man alle Elemente skalieren möchte - das mag bei "normalen" Bearbeitenfenstern die Regel sein, bei komplexeren Fenstern ist dies aber selten so.
Nehmen wir einmal ein typisches Hauptfenster: Das Menü soll in der Regel nicht mit skaliert werden, sondern nur oben angepinnt sein (Dockpanel). Bei Buttons will man häufig gleiche Größe haben - geht wunderbar mit einem horizontal ausgerichteten Stackpanel...
Und auch bei einem solchen Fenster wie von dir beschrieben, habe ich in der Regel noch ein oder zwei Stackpanels als unterste Elemente im Grid, wo die Buttons eingebettet werden.
Ganz davon abgesehen finde ich auch eine Mindestbreite nicht schlecht, und Margins kann man in deinen Fall auch durch weitere Spalten/Zeilen mit fixen Größen lösen (Je nach dem was im konkreten Fall angemessener erscheint - ich nutze z.B. hier eine Konstante - da mein Chef dann nur an einer Stelle ändern muss um seine Meinung zu Abständen umzusetzen ;p).
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="420" MinWidth="420"> <Grid Name="Kunde" Margin="4"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="4"/> <RowDefinition Height="*"/> <RowDefinition Height="4"/> <RowDefinition Height="*"/> <RowDefinition Height="4"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="4"/> <ColumnDefinition Width="*"> </Grid.ColumnDefinitions> <Label Grid.Column="0" Grid.Row="0" Content="Vorname:"/> <TextBox Grid.Column="0" Grid.Row="2" Text="Max" TextWrapping="Wrap"/> <Label Grid.Column="0" Grid.Row="4" Content="Produkt:"/> <TextBox Grid.Column="0" Grid.Row="6" Text="Murks" TextWrapping="Wrap"/> <ListBox Grid.Column="2" Grid.Row="0" Grid.RowSpan="7"/> </Grid> </Window>
-
Ja, ein paar Elemente gibt es immer die sich nicht Resizen sollen. Da könnte man diese Panels verwenden. Ich werd dann mal weiter herumbasteln.
Vielen Dank