Unexpected auto grid column width - wpf

the code below is a small snippet of a big wpf Window I am using in my Project. It produces the linked wpf Window.
I am wondering why my last grid column is so wide. I am expecting that the width of the last column depends on the width of the button, because the column width is set to "Auto".
If I remove the columnspan of the StackPanel the column width will be correct but then the CheckBoxes are not aligned to right side.
I hope you have understood my problem. My aim is, that the last column is as small as possible, the checkboxes are at the right side and the rest stays at it is.
Because this snippet is part of a bigger wpf window I cannot remove any grid rows or columns.
Thank you very much for your help.
Best regards.
WPF Window
<Window x:Class="TestProject.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DesignHeight="152.429" d:DesignWidth="403">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Grid.Row="0"
Margin="5"
Grid.ColumnSpan="2"/>
<Button Grid.Column="2"
Grid.Row="0"
Margin="5"
Width="40"/>
<ComboBox Grid.Column="0"
Grid.Row="1"
Margin="5"
Grid.ColumnSpan="3"/>
<Image Grid.Column="0"
Grid.Row="2"/>
<StackPanel Grid.Column="1"
Grid.Row="2"
Grid.ColumnSpan="2">
<CheckBox Margin="5"
Content="checkbox content 1"/>
<CheckBox Margin="5,0,5,5"
Content="checkbox content 2"/>
</StackPanel>
</Grid>

You can put a grid inside another grid.
Here is the code that will help you achieve your goal.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Grid.Row="0"
Margin="5"
Grid.ColumnSpan="2"/>
<Button Grid.Column="2"
Grid.Row="0"
Margin="5"
Width="40"/>
<ComboBox Grid.Column="0"
Grid.Row="1"
Margin="5"
Grid.ColumnSpan="3"/>
<Grid Name="GridInsideAGrid"
Grid.Column="0"
Grid.Row="2"
Grid.ColumnSpan="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" />
<StackPanel Grid.Column="1">
<CheckBox Margin="5"
Content="checkbox content 1"/>
<CheckBox Margin="5,0,5,5"
Content="checkbox content 2"/>
</StackPanel>
</Grid>
</Grid>

Related

Stretch the child grid

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StatusBar Height="25" Grid.Row="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StatusBarItem Content="Text" FontSize="10" Height="20" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0"/>
<StatusBarItem Content="Text" FontSize="10" Height="20" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Column="1"/>
<ProgressBar Width="100" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="2"/>
</Grid>
</StatusBar>
</Grid>
Please help the beginner.
I want to create a StatusBar and divide it into 3 elements. I want to align the first element on the left side. The second by right. The third in the center.
In the first and second elements I want to locate the text. In the third I want to locate StatusBar.
Why does the grid in StatusBar not want to stretch to the StatusBar and format the elements?
What am I doing wrong?
Sorry for mistakes, if any.
Because the default ItemsPanel of the StatusBar won't tell us how much space we have, we need to provide it with one that does (like grid).
A possible solution is as follows (using the grid as the ItemsPanel straight away) :
<StatusBar Height="25" Grid.Row="5">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem Content="Text" FontSize="10" Height="20" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="0"/>
<StatusBarItem Content="Text" FontSize="10" Height="20" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Column="1"/>
<ProgressBar Width="100" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="2"/>
</StatusBar>

How to make contents having equal space (width & hight) to resize upon changing of window size in XAML?

I have the following code of XAML in WPF. This generates the grid with equal size of columns & rows (as shown in figure 1.)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="A" Background="Green"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="AB" Background="Red"/>
<TextBlock Grid.Row="2" Grid.Column="2" Text="ABC" Background="Blue"/>
<TextBlock Grid.Row="3" Grid.Column="3" Text="ABCD" Background="Yellow"/>
</Grid>
Figure 1.
But when I put this grid in a viewbox (like the code below), the rows & column remains no more equally in size (as shown in figure 2.).
<Viewbox Stretch="Uniform">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="A" Background="Green"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="AB" Background="Red"/>
<TextBlock Grid.Row="2" Grid.Column="2" Text="ABC" Background="Blue"/>
<TextBlock Grid.Row="3" Grid.Column="3" Text="ABCD" Background="Yellow"/>
</Grid>
</Viewbox>
Figure 2.
How can I make this grid with equal size of rows & column inside a viewbox?
You can enforce size-sharing like this:
<Grid Grid.IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition SharedSizeGroup="A"/>
<RowDefinition SharedSizeGroup="A"/>
<RowDefinition SharedSizeGroup="A"/>
<RowDefinition SharedSizeGroup="A"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="B"/>
<ColumnDefinition SharedSizeGroup="B"/>
<ColumnDefinition SharedSizeGroup="B"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
That's the behavior of ViewBox
Taken from internet
The ViewBox is a very useful control in WPF. If does nothing more than
scale to fit the content to the available size. It does not resize the
content, but it transforms it.
why use viewbox when you don't want this, try another control.
Instead of using a Grid try using a UniformGrid:
<Viewbox Stretch="Uniform">
<UniformGrid Rows="4" Columns="4">
<TextBlock Grid.Row="0" Grid.Column="0" Text="A" Background="Green"/>
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock Grid.Row="1" Grid.Column="1" Text="AB" Background="Red"/>
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock Grid.Row="2" Grid.Column="2" Text="ABC" Background="Blue"/>
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock />
<TextBlock Grid.Row="3" Grid.Column="3" Text="ABCD" Background="Yellow"/>
</UniformGrid>
</Viewbox>
Just make sure you set Rows And Columns, and instead of saying which row/column each child element is, you just enter them in order.

Vertical and horizontal GridSplitter

I have a grid and I am trying to put both vertical and horizontal GridSplitters. It's my main grid and I would like it to be as fluid as possible.
On my second definition I get "Missing Grid.Column setter for non-first child"
I've found loads of documentation on implementing one or the other. I have found nothing suggesting that I can do both. But, our industry is made of people wanting to push functionality.
Here is my XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="50*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height="50*"></RowDefinition>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"></GridSplitter>
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch"></GridSplitter>
You need to set Grid.Column for grid splitters and also you need
HorizontalAlignment="Stretch" -> for horizontal splitter
VerticalAlignment="Stretch" -> for Vertical splitter
so your code looks like --
<GridSplitter Grid.Column="1" Width="5" Grid.RowSpan ="3" VerticalAlignment="Stretch"></GridSplitter>
<GridSplitter Grid.Row="1" Height="5" Grid.ColumnSpan ="3" HorizontalAlignment="Stretch"></GridSplitter>
ResizeHehavior="PreviousAndNext" needs to be added to allow proper adjustment of both columns and rows. See below for my sample.
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="50*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="5"></RowDefinition>
<RowDefinition Height="50*"></RowDefinition>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="1" Width="5" Grid.RowSpan ="3"
VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext">
</GridSplitter>
<GridSplitter Grid.Row="1" Height="5" Grid.ColumnSpan ="3"
HorizontalAlignment="Stretch" ResizeBehavior="PreviousAndNext">
</GridSplitter>
<Button Grid.Row="0" Grid.Column="0" Content="1,1" FontSize="30"/>
<Button Grid.Row="2" Grid.Column="0" Content="3,1" FontSize="30"/>
<Button Grid.Row="0" Grid.Column="2" Content="1,3" FontSize="30"/>
<Button Grid.Row="2" Grid.Column="2" Content="3,3" FontSize="30"/>
</Grid>
You can set the direction as follows:
<GridSplitter ResizeDirection=”Rows”/>
or
<GridSplitter ResizeDirection=”Columns”/>
However, when you set Alignment to either Horizontal or Vertical, the default ResizeDirection=”Auto” will most likely choose a fitting resize direction.

Vertically align a WPF RadioButton bullet and stretch its contents

I want to use a grid, stretched across the entire available area, as the content for a RadioButton, and I want the RadioButton's bullet to be vertically aligned.
Getting the grid to stretch across the entire area is easy enough, I just set the HorizontalContentAlignment property on the RadioButton:
<RadioButton HorizontalContentAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock>Foo</TextBlock>
<TextBox Grid.Column="1"/>
<TextBlock Grid.Row="1">The quick brown fox</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1"/>
</Grid>
</RadioButton>
And following Simon Weaver's answer to this older question, I can vertically align the radio button's bullet relatively easily:
<RadioButton HorizontalContentAlignment="Stretch">
<TextBlock Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock>Foo</TextBlock>
<TextBox Grid.Column="1"/>
</Grid>
<LineBreak/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1">The quick brown fox</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1"/>
</Grid>
</TextBlock>
</RadioButton>
The trouble is, having done that, the content no longer stretches.
How can I get a vertically aligned bullet and a stretching grid?
The TextBlock is being stretched properly, but the grid inside it is not. Presumably that's just the way TextBlock works.
The following is a bit hacky, but it works:
<RadioButton HorizontalContentAlignment="Stretch">
<TextBlock Name="Text" Grid.IsSharedSizeScope="True">
<Grid Width="{Binding ElementName=Text, Path=ActualWidth}">
This would work for the visual effect. You didn't list any functional requirements so i'm not sure if it will work for you without some event mapping or not.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RadioButton Grid.Column="0" Grid.RowSpan="2" Content=""/>
<TextBlock Grid.Column="1">Foo</TextBlock>
<TextBox Grid.Column="2"/>
<TextBlock Grid.Row="1" Grid.Column="1">The quick brown fox</TextBlock>
<TextBox Grid.Row="1" Grid.Column="2"/>
</Grid>

Grid Splitter problem in WPF

I want a layout like VS 2008. In which I want two columns and second columns is again split into two.
I done that in the xaml mentioned below, but the GridSplitter is not visible vertically ( which split two columns).
I want both the GridSplitters to be resizable. One GridSplitter resizes the Left Hand Pane and Right Hand Pane and another GridSplitter resizes the subgrid's top pane and right pane..
The Second GridSplitter is working through this XAML but I am not able to produce XAML code that Splits the Right hand Pane and Left hand pane..
Pleas Help!!
<Window x:Class="AlarmUI_2.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Background="Aqua" Grid.Column="0" >
<TextBlock FontSize="35" Foreground="#58290A"
TextWrapping="Wrap">Left Hand Side</TextBlock>
</StackPanel>
<GridSplitter Grid.Column="0" ResizeDirection="Auto"
Grid.RowSpan="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Background="Red">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="5" Background="Gray"
VerticalAlignment="Top" HorizontalAlignment="Stretch" />
<ListBox Grid.Row="1" Background="Violet" Margin="0,5,0,0">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
</Grid>
</Grid>
</Window>
Change your vertical Splitter to
<GridSplitter Grid.Column="0" Width="5" ResizeDirection="Auto"
Grid.RowSpan="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"/>
This will be much better way to use GridSplitter
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Background="Aqua" Grid.Column="0" >
<TextBlock FontSize="35" Foreground="#58290A"
TextWrapping="Wrap">Left Hand Side</TextBlock>
</StackPanel>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch"/>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="5" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Background="Red">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Background="Gray" HorizontalAlignment="Stretch"/>
<ListBox Grid.Row="2" Background="Violet">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
</Grid>
</Grid>
The GridSplitters should probably be on their own row/column in the grid, not sharing a cell with the other controls.
Your gridsplitter is behind the other controls that's why you can't see it. You can either move it to the bottom in your XAML file (so it is added last) or use the Panel.ZIndex attached property. Additionally you have to set the width for the splitter correctly correctly:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Background="Aqua" Grid.Column="0" >
<TextBlock FontSize="35" Foreground="#58290A"
TextWrapping="Wrap">Left Hand Side</TextBlock>
</StackPanel>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Background="Red">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="5" Background="Gray"
VerticalAlignment="Top" HorizontalAlignment="Stretch" />
<ListBox Grid.Row="1" Background="Violet" Margin="0,5,0,0">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
</Grid>
<GridSplitter Grid.Column="0" ResizeDirection="Columns"
Grid.RowSpan="1" Width="5"
HorizontalAlignment="Right"/>
</Grid>
I have acheived the functionality, the XAML is mentioned below:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Background="Aqua" Grid.Column="0" >
<TextBlock FontSize="35" Foreground="#58290A"
TextWrapping="Wrap">Left Hand Side</TextBlock>
</StackPanel>
<GridSplitter HorizontalAlignment="Right" ResizeDirection="Columns" Width="5" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Background="Red">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="5" Background="Gray"
VerticalAlignment="Top" HorizontalAlignment="Stretch" />
<ListBox Grid.Row="1" Background="Violet" Margin="0,5,0,0">
<ListBoxItem>Hello</ListBoxItem>
<ListBoxItem>World</ListBoxItem>
</ListBox>
</Grid>
</Grid>

Resources