Resize and Keep Controls in Thirds - c#

Is it possible to get controls to automatically divide a space in thirds as the window resizes? It is easy enough to do in code, but I'd like to set the parameters directly in the xaml if possible.

Use the Grid control. It takes up whatever space is available. You can get thirds by doing (assuming you want three columns)
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinitions Width="*"/>
<ColumnDefinitions Width="*"/>
<ColumnDefinitions Width="*"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"/>
<Button Grid.Column="1"/>
<Button Grid.Column="2"/>
</Grid>

Related

Set 2-Line text box

Goal:
I'm trying to create a TextBox with space for exactly 2 lines.
The content will later be filled into a document which has a maximum space for two lines.
The user should be able to see that visually in the application to generate the Document:
Current Situation / Issue
The TextBox sits in a Grid with <RowDefinition Height="auto"></RowDefinition>. This leads the Textbox to occupy exactly 1 Line of space (marked in yellow):
Only when the first letter is beeing typed, the textbox expands to two lines due to MinLines="2". I do have the Idea to set a static height to the Grid.Row but to be honest, I really dislike static sizing and I feel that it is not the apropriate solution.
Additionally, eventhough MaxLines="2" the textbox will happily wrap around any number of lines.
I have set MaxLength="200" - It kind of does the Job but has nothing to do with the actual text size.
(iiiii vs WWWWW)
Current Code:
<Grid x:Name="EigenbelegGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<!-- Preset -->
<Label Content="Preset" Grid.Column="0" Grid.Row="0"></Label>
<ComboBox x:Name="TemplateSelection_DropDown" Grid.Column="1" Grid.Row="0" IsEditable="True"
<Button x:Name="SavePreset_Button" Content="Save" Grid.Column="2" Grid.Row="0"></Button>
<Button x:Name="DeletePreset_Button" Content="Delete" Grid.Column="3" Grid.Row="0"></Button>
<!-- Reasoning -->
<Label Content="Begründung" Grid.Column="0" Grid.Row="1"></Label>
<TextBox x:Name="Reasoning_TextBox" Grid.Column="1" Grid.Row="1" MinLines="2" MaxLines="2" TextWrapping="Wrap" MaxLength="200"></TextBox>
</Grid>
After being loaded to visual tree, if TextBox is blank, DesiredSize will contain the height of one line plus the height of other causes, and ExtentHeight will contain the height of one line. We can use this two to calculate the actual height we need. In your case, it will be like
<TextBox x:Name="Reasoning_TextBox" Grid.Column="1" Grid.Row="1" MaxLines="2" TextWrapping="Wrap"
Loaded="Reasoning_TextBox_Loaded"></TextBox>
private void Reasoning_TextBox_Loaded(object sender, RoutedEventArgs e)
{
TextBox t = (TextBox)sender;
t.Height = t.DesiredSize.Height + t.ExtentHeight * (t.MaxLines - 1);
}

Why Image goes beyond Grid?

I'm making a program for viewing images and I met with a problem that wide pictures go beyond the window.
I set the property "stretch" to "uniform" but it doesn't work with wide pictures. What can I do?
An example of this problem:
And if I expand window it will be this
This is XAML of image:
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="300" Width="0.1*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition MinWidth="300" Width="*"/>
</Grid.ColumnDefinitions>
<TreeView Style="{StaticResource BorderStyle}" ScrollViewer.VerticalScrollBarVisibility="Auto" Name="folders" Grid.Row="0" Grid.Column="0" TreeViewItem.Expanded="treeView_Expanded">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<StackPanel>
<Label HorizontalAlignment="Stretch" Cursor="Hand" Content="{Binding fileName}" Foreground="#FFF"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<GridSplitter Margin="-5 5 -5 5" Cursor="SizeWE" Grid.Row="0" Grid.Column="1" VerticalAlignment="Stretch" ShowsPreview="False" Width="5" HorizontalAlignment="Center" Background="Transparent"/>
<Border Style="{StaticResource BorderStyle}" Grid.Row="0" Grid.Column="2">
<Image Name="ImageViewer"/>
</Border>
</Grid>
The image is sizing itself to its parent, but the MinWidth="300" in your first and third grid column definitions is forcing the parent to be wider than the window. MinWidth overrides Width if the two disagree.
If you change to these values, it won't do that any more except when the window is too narrow to be much use anyway:
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30" Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition MinWidth="30" Width="4*"/>
</Grid.ColumnDefinitions>
I'm not sure what you were getting at with what you had: The number/* Width values (the System.Windows.GridLength structure, whose documentation meets the usual regrettable standard of WPF documentation) work in a not immediately obvious way. The following creates three columns. The middle one is sized to its content. The first one uses one eleventh of the remaining space; the last one uses ten elevenths of the remaining space. "*" means "1*". We add all the numeric values and pro-rate the available space accordingly.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.1*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
That's exactly equivalent to this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
It's proportional.
So your MinWidth values seem wrong to me, unless you have a truly enviable monitor setup. What I've given you will make the image area four times the width of the left sidebar, which is a rough guess at what you seem to be looking for. I like those proportions.

How to structure a stacked form with WPF XAML?

On my Window, I've got a GroupBox. I'd like to build out a horizontally aligned form inside of that GroupBox. By horizontally aligned, I mean a form where the label and the input reside on the same grid row or x axis. Separate form labels + inputs reside on their own row.
Since a GroupBox can only have one child content, I assume I need to either use a Grid or StackPanel. I'm trying to use a StackPanel because that seems simpler and should achieve what I'm aiming for.
The issue I'm trying to figure out is how to group the input and label into one unit so they can reside horizontally next to each other, but stack vertically as a pair within the StackPanel.
It's probably best to use a Grid that way you an get the labels and inputs to line up vertically. While it's not impossible with a stack panel it's a whole lot harder. If you set the grid's RowDefinition heights to "Auto" the grid will only be as tall as it needs to be:
<GroupBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Label1"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Input1}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Label2"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Input2}"/>
etc.
</Grid>
</GroupBox>
You'll probably need to play around with margins and/or padding and horizontal alignments to get the layout exactly how you want it, but this should give you the control you need to achieve what you want.
you can use a stackpanel with orientation equal to vertical inside your groupbox and inside that stackpanel you can have another stackpanel with orientation equal to horizantal for your label and input just like following sample code.
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical">
<StackPanel Name="input1" Orientation="Horizontal">
<Label Content="input1"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input2" Orientation="Horizontal">
<Label Content="input2"/>
<TextBox/>
</StackPanel>
<StackPanel Name="input3" Orientation="Horizontal">
<Label Content="input3"/>
<TextBox/>
</StackPanel>
</StackPanel>
</GroupBox>
One feature you might find useful is grid shared size scope. It can help you align elements in multiple different Grids, by sharing their column\row sizes, like this:
<GroupBox Header="Sample GroupBox">
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input11" Grid.Column="0" />
<TextBox Grid.Column="1" Width="100"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input2222222" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="firstGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="secondGroup" />
</Grid.ColumnDefinitions>
<Label Content="input3333333333333" Grid.Column="0" />
<TextBox Grid.Column="1"/>
</Grid>
</StackPanel>
</GroupBox>
I don't say that it is necessary in the code above, but that is just example. Often, you want to use grid in for example ItemTemplate of ItemsControl, and you want all items to be aligned. Here shared size scope might help.

WPF Create Sidebar Navigation

I am curious about how to create a sidebar navigation something like:
I tried using an uniform grid but there ended up being too much spacing between "buttons" and I'm not sure if it's possible to modify the tab control to act like full width buttons instead of overhead tabs.
Also if if its possible to add icons that would be a huge plus.
You can make a Gridcolumn in your Standard grid with your wished Width. The into this Column you can put a stackpanel which fills your buttons from top to bottom.
Like That:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Button Height="40">Test</Button>
<Button Height="40">Test2</Button>
</StackPanel>
</Grid>
It would look like this:
If i missunderstod you please tell me and im gona edit it.
To add Images you can then create another grid in your Button with two columns: Like this:
<Button>
<Grid Height="40" Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="pack://siteoforigin:,,,/Resources/dll.png"></Image>
<TextBlock Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">Text</TextBlock>
</Grid>
</Button>
Note that you have to set your grid to Width="200" like you set your main Grid.Column because the Grid would not be the whole width of the button if you would not set it too 200.
Then the List would look like this:

Button on title of ChildWindow (Silverlight) design issue

I'm designing Silverlight ChildWindow and I met one intersting problem. I defined a button on a window title as follows:
<ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" Width="100"
Margin="300,0,0,0" />
</Grid>
</ChildWindow.Title>
This window is resizable. When you try to resize the window, the "btnHelp" button is covered by the close button, and the "btnHelp" button is not aligned to the edge of the window also. I tried before to use a StackPanel, also I used margins in both variants (StackPanel and Grid) and they didn't help me properly. The variant in the code is latest:) Could you please give a hint, what can I do with that?
Thanks in an advance.
This is a result of what appears to be a strange choice in the ChildWindow's control template -- the Title content is not stretched, so you can't really right-align anything without hard-coding it. So, you could go ahead and just apply fixed widths to the Grid column widths:
<controls:ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" />
</Grid>
</controls:ChildWindow.Title>
That's quick-and-dirty, but not very satisfying. An alternative would be to modify the ControlTemplate (at the link above) so that it behaves how you would expect. Find the ContentControl that displays the Title, and make it stretch to fill the available space, by adding HorizontalContentAlignment="Stretch":
<Style TargetType="controls:ChildWindow" x:Key="MyChildWindowStyle">
<!-- etc ... -->
<ContentControl Content="{TemplateBinding Title}" FontWeight="Bold"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch" IsTabStop="False" Margin="6,0,6,0" VerticalAlignment="Center"/>
<!-- etc ... -->
</Style>
This allows you to use the normal layout controls like Grid, and it will render as expected:
<controls:ChildWindow Style="{StaticResource MyChildWindowStyle}"
...
<controls:ChildWindow.Title>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is textblock" Grid.Column="0"/>
<Button Content="Help" Name="btnHelp" Grid.Column="1" Width="100"/>
</Grid>
</controls:ChildWindow.Title>

Categories