Expand the Grid with when the Expander is expanded - c#

I have a problem designing my GUI in wpf.
How do i set the Grid ColumnDefinition Width dynamically,
I have a expander. And when the expander is clicked the grid should also expand and adjust with the size of the expander
As of now i have this GUI
enter image description here
And this is the xaml code
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="127"/>
<ColumnDefinition Width="665*"/>
</Grid.ColumnDefinitions>
<Expander Background="Gray" x:Name="expander" ExpandDirection="Right" Expanded="Expander_Expanded" >
<Expander.Header>
<TextBlock Text="Objects">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<StackPanel Margin="10,4,0,0">
<CheckBox Margin="4" Content="Option 1" />
<CheckBox Margin="4" Content="Option 2" />
<CheckBox Margin="4" Content="Option 3" />
</StackPanel>
<!-- Stuff XD -->
</Expander>
<Grid Grid.Column="1" Background="Red"/>
</Grid>
As of now the ColomnDefinition width is 127
I want it to adjust to at least 30. So the window will be filled with other stuff
like this
enter image description here
But my problem is how do i expand the grid when the expander is expanded.
And another thing. I can't get the size of the expander when expanded. It gives me NaN which i can't use to set the columndefinition width
Thank you so much. Sorry for my bad english

Use Auto in first column Width and it will define size of expander based on content.
If you would like that column "0" has some min Width just set the property MinWidth. (but in that case I will not recommend, but show below)
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
Also I will recommend use GridSplitter, then you will have splitter between two columns that allows to change width of columns by user in UI
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="DarkSalmon"/>
Also in expander you can only have one user-control, so "stuff" you said need to be inside some layout control like stack-panel,dock or another grid etc.
Let me know if it works as you expected.

Related

How to make a rounded Border and Background colour exactly fit the text extents in a TextBlock?

I've got the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Level}"/>
</Grid>
Level is basically a log level (Verbose, Information, Warning, Error).
First I would like to add a background colour but only to the text itself.
If I do <TextBlock Text="{Binding Level}" Background="Yellow"/> then I end up with something like this:
Verbose
I can workaround that by doing the following:
<TextBlock>
<Run Text="{Binding Level}" Background="Yellow"/>
</TextBlock>
And now I correctly end up with:
Verbose
But now I would like to round the corners of just the text itself, and that ... I can't find a way to do and would appreciate some help with.
I've tried adding a Border to the TextBlock but that creates a border around the whole TextBlock, not just the text inside it.
If you set an HorizontalAlignment and VerticalAlignment on a FrameworkElement like a Border or TextBlock, it will prevent it from stretching to its parent size (which is the default behavior).
You can write the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Border Background="Yellow" CornerRadius="5" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Text="Hello"/>
</Border>
</Grid>
And the Border only takes the space needed to fit its child TextBlock.

How to make textboxes width dynamically like buttons in xaml

I have textboxes with some textblocks above it.
I want my application to have resizable width (not height) so I have setted only MinWidth for window. So when I click on right or left border of window I can scale it however I want.
My problem is, that when I use textboxes I don't get result what I would like to have.
If I position textboxes with textblock above it on MinWidth of window, after making the window bigger those textboxes will stay with same width on the same place according to ColumnDefinitions.
It does make sence since those textboxes have fixed width setted on 160 but if I try same thing with buttons according same columndefinitions and stuff those buttons gonna stretch according window size and it will be sorted by columndefintions.
Is there way how to acomplish same thing with textboxes? So when I stretch window from 1050px to full size 1920px mine textboxes would change width so it can be dynamically? Width="Auto" doesn't solve it for me
Adding images below so you can imagine it better hopefully.
xaml:
<UserControl x:Class="App.NewUI.Textboxes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:App.NewUI"
mc:Ignorable="d"
d:DesignHeight="720" MaxHeight="720" d:DesignWidth="1050">
<Border Padding="10">
<StackPanel>
<!-- TextBoxes + update button -->
<Grid Margin="0 5 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtBoxFirstname" Text="{Binding SelectedItem.Firstname, ElementName=dg}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160"/>
<TextBox x:Name="txtBoxLastname" Text="{Binding SelectedItem.Lastname, ElementName=dg}" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160"/>
<TextBox x:Name="txtBoxTelephone" Text="{Binding SelectedItem.Telephone, ElementName=dg}" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160"/>
<TextBox x:Name="txtBoxBorn" Text="{Binding SelectedItem.Born, ElementName=dg}" Grid.Column="3" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160"/>
<TextBox x:Name="txtBoxCategory" Text="{Binding SelectedItem.Category, ElementName=dg}" Grid.Column="4" HorizontalAlignment="Left" VerticalAlignment="Center" Width="160"/>
<Button x:Name="btnUpdateRecord" Content="Update Record" Grid.Column="5" Click="btnUpdateRecord_Click"/>
</Grid>
<!-- datagrid -->
<Grid Margin="0 15 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<DataGrid x:Name="dg" Grid.Column="0" Margin="0,0,0,-350" Width="auto" Height="350"/>
</Grid>
</StackPanel>
</Border>
I've tried to set textboxes width to auto but then textboxes will be tiny without text and won't stretch anyway. Thank you for any tip
Imgur images of window
Deleting fixed width and set horizontal alignment to strech figured it out.
<TextBox x:Name="txtBoxFirstname" Text="{Binding SelectedItem.Firstname, ElementName=dg}" Grid.Column="0" HorizontalAlignment="stretch" VerticalAlignment="Center"/>

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.

C# wpf how to know a control (es. listbox) size when not specified

I have two borders in a winwdow, the first one contains a listbox which has size set through margins. So I can change the window size--->the border changes---> the listbox changes. I'd like to know what it's width is but the width property reports Nan while the actualWidth report 0.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border x:Name="Border1" BorderBrush="Gainsboro" BorderThickness="5" CornerRadius="8,8,3,3" Margin="10,10,168.8,10.4" >
<ListBox x:Name="lbButtons" Background="{x:Null}" BorderBrush="{x:Null}" Height="338" Margin="0,0,0.4,0"/>
</Border>
<Border x:Name="Border2" BorderBrush="Gainsboro" BorderThickness="5" CornerRadius="8,8,3,3" Grid.ColumnSpan="2" Margin="263,10,9.2,10" />
</Grid>
This is something valid for each control: how to know its present size when it's not specified?
thanx
It is possible that the component is not yet displayed at the point where you get its size. You can get the right actualWidth in the loaded event of the object.

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