Binding Grid Column Width inside UserControl to parent Grid Column Width - wpf

I have a WPF Grid with two rows.
First row contains 4 columns and each column contains a Button.
Second row contains user control with colspan of 3.
The custom control contains another Grid with two columns.
I would like to set the width of the first column in UserControl's grid to the width of the second column in the MainWindow's grid.
In the example below "nested column 0"'s width should be the same as "Column 1"'s width.
I tried with ElementName but it did not work out.
Any ideas how to do it?
<Window x:Class="TestElementName.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:trace="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:local="clr-namespace:TestElementName"
Title="MainWindow" Height="200" Width="600">
<Grid Tag="YeahGrid" Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" Tag="Hallelujah" x:Name="ColDef2"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0">Column 0</Button>
<Button Grid.Column="1" Grid.Row="0" MinWidth="180">Column 1</Button>
<Button Grid.Column="2" Grid.Row="0" MinWidth="115">Column 2</Button>
<Button Grid.Column="3" Grid.Row="0">Column 3</Button>
<local:ucButton Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="3" BorderBrush="Red" BorderThickness="1" />
</Grid>
</Window>
User control is as follows:
<UserControl x:Class="TestElementName.ucButton"
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:trace="clr-namespace:System.Diagnostics;assembly=WindowsBase"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0">nested column 0</Button>
<Button Grid.Column="1">nested column 1</Button>
</Grid>
</UserControl>
Thank you!

You can do this using a SharedSizeGroup. This allows you to link the width of designated columns in multiple Grids. (It also works for row height!)
First you need to define a SharedSizeScope on a control that encompasses all of the columns that will share widths. You can use your YeahGrid for this:
<Grid Tag="YeahGrid" Name="grid" Grid.IsSharedSizeScope="True">
Then set the SharedSizeGroup property on the columns you want to align. In the Window:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" Tag="Hallelujah" x:Name="ColDef2" SharedSizeGroup="HallelujahSSG" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
And in the UserControl:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="HallelujahSSG"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
Now the widths of all Grid columns with the same SharedSizeGroup name are linked, effectively bound to the width of the column that requires the most space (in this case Column 1 in YeahGrid).

In your UserControl Xaml, you mentioned both ColumnDefinition width = "Auto". On that place please add the MinWidth attribute as per your requirements.
For your scenario you can add ---
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="180"/>
<ColumnDefinition Width="Auto" MinWidth="115"/>
</Grid.ColumnDefinitions>
Because you are using in mainwindow like this
<Button Grid.Column="1" Grid.Row="0" MinWidth="180">Column 1</Button>
<Button Grid.Column="2" Grid.Row="0" MinWidth="115">Column 2</Button>

Related

WPF how to prevent focus wrap on several buttons?

I am curious if anyone knows if it is possible to prevent "focus wrap" on a series of buttons. If I merely add a few buttons to a grid within WPF like so:
<Window x:Class="ButtonList_Test.MainWindow"
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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ButtonList_Test"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel x:Name="myStackPanel" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid x:Name="myGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0">A</Button>
<Button Grid.Column="1" Grid.Row="0">B</Button>
<Button Grid.Column="2" Grid.Row="0">C</Button>
<Button Grid.Column="3" Grid.Row="0">D</Button>
<Button Grid.Column="4" Grid.Row="0">E</Button>
</Grid>
</StackPanel>
</Window>
And run the program, it will produce 5 small buttons in a nice single row.
If I click on the button in the middle (C), and then start to use any of the keyboard arrow keys, you will notice that the focus will begin to traverse these buttons in the direction of the key you are pressing.
If the dotted line reaches the "E" button, and I press one more time to the right, it will wrap back to the "A" button.
Is there any way to prevent this functionality?
Thank you in advance for any insight you may be willing to provide,
You can try Focusable="False". As far as I know, traverse controls with arrow keys or Tab keys can be happened by group of Focusable="True" controls only.
For example, if you try
<Button Grid.Column="0" Grid.Row="0">A</Button>
<Button Grid.Column="1" Grid.Row="0">B</Button>
<Button Grid.Column="2" Grid.Row="0" Focusable="False">C</Button>
<Button Grid.Column="3" Grid.Row="0">D</Button>
<Button Grid.Column="4" Grid.Row="0">E</Button>
and click B then press right key, D will be focused. So if you want to prevent every traverse, you can set Focusable="False" to every Buttons.
Set the IsTabStop property of all buttons to false or define an implicit Style that sets this property for all buttons:
<StackPanel x:Name="myStackPanel" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid x:Name="myGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Button">
<Setter Property="IsTabStop" Value="False" />
</Style>
</Grid.Resources>
<Button Grid.Column="0" Grid.Row="0">A</Button>
<Button Grid.Column="1" Grid.Row="0">B</Button>
<Button Grid.Column="2" Grid.Row="0">C</Button>
<Button Grid.Column="3" Grid.Row="0">D</Button>
<Button Grid.Column="4" Grid.Row="0">E</Button>
</Grid>
</StackPanel>

Toolbar isn't showing overflow when hosted in UserControl

Hosted in a Window, I have a main UserControl composed of other UserControls.
One of these contains a ToolBar with a few Buttons on it. I place this at the top of my main UserControl by setting it's Grid.Row property to 0. However, when making the Window smaller, the Buttons just disappear and no overflow is shown. I've messed with the overflow properties a bit but no luck.
Here's the UserControl containing the ToolBar.
<UserControl x:Class="TestProj.Views.ToolBarView"
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"
mc:Ignorable="d"
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="706"/>
<ColumnDefinition Width="319"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<ToolBar Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<Button Content="Button1" />
<Button Content="Button2" />
<Button Content="Button3" />
<Button Content="Button4" />
<Button Content="Button5" />
<Button Content="Button6" />
</ToolBar>
</Grid>
</UserControl>
Here's my main UserControl which is hosted inside of a Window, and hosts the ToolBar UserControl:
<UserControl x:Class="TestProj.MainControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-TestProj.Views"
mc:Ignorable="d" d:DesignHeight="737.239" d:DesignWidth="1026"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="256*"/>
<ColumnDefinition Width="256*"/>
<ColumnDefinition Width="256*"/>
<ColumnDefinition Width="430*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto">
</RowDefinition>
<RowDefinition Height="608*"/>
<RowDefinition Height="Auto">
</RowDefinition>
</Grid.RowDefinitions>
<views:ToolBarView HorizontalAlignment="Left" x:Name="OnyxToolBar" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" />
</Grid>
</UserControl>
And here's an example .gif of me resizing the Window, just the top where the UserControl containing the ToolBar is:
The problem is your fixed sized columns in your UserControl aka ToolBarView
you can not give to some control (does not matter if it is a ToolBar or not) a fixed size value and expect to have "dynamic size"
in your situation you could do something like this
change this
<Grid.ColumnDefinitions>
<ColumnDefinition Width="706"/>
<ColumnDefinition Width="319"/>
</Grid.ColumnDefinitions>
to this (for example)
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

WPF style for Grid with defined columns and rows? [duplicate]

This question already has answers here:
How to create reusable WPF grid layout
(6 answers)
Closed 3 years ago.
In my application I have a lot of grids like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!-- ... -->
</Grid>
They have 4 columns and 3 rows and column widths are set to some value.
Can I create style or some other kind of template to simplify my window that uses 20 grids like this?
I know, that I can create styles for column definitions one by one to avoid Width="10" everywhere, but is it possible to do something like this?
<Grid Style="{StaticResource GridWith4ColumnsAnd3Rows}">
<!-- ... -->
</Grid>
You can't set the RowDefinitions or ColumnDefinitions properties in a Style because they are not dependency properties.
But you could create a custom class that inherits from Grid and adds the ColumnDefinitions and RowDefinition in the constructor:
public class CustomGrid : Grid
{
public CustomGrid()
{
ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(10) });
//...
ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
}
}
Usage:
<local:CustomGrid>...</local:CustomGrid>
Alternatively, you could define an attached behaviour that creates the RowDefinitions and ColumnDefinitions.
Nice answer is here:
How to create reusable WPF grid layout
I have used <ItemsPanel> control with Grid inside.
Style (in my App.xaml):
<Style x:Key="SchedulerFieldGridStyle1" TargetType="ItemsControl" >
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid Background="LightSteelBlue" Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Part of MainWindow.xaml before:
<Grid Background="LightSteelBlue" Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.ColumnSpan="4" Content="Day of week"/>
<Label Grid.Column="0" Grid.Row="1" Content="From"/>
<ComboBox Grid.Column="1" Grid.Row="1" />
<Label Grid.Column="2" Grid.Row="1" Content="To"/>
<ComboBox Grid.Column="3" Grid.Row="1" />
</Grid>
Part of MainWindow.xaml after:
<ItemsControl Style="{StaticResource SchedulerFieldGridStyle1}">
<Label Grid.ColumnSpan="4" Content="Day of week"/>
<Label Grid.Column="0" Grid.Row="1" Content="From"/>
<ComboBox Grid.Column="1" Grid.Row="1"/>
<Label Grid.Column="2" Grid.Row="1" Content="To"/>
<ComboBox Grid.Column="3" Grid.Row="1"/>
</ItemsControl>

UserControl cropped when used in MainWindow

Hello Stackoverflowers !
I'm creating a list with a searchbar in XAML, and when i tried to use my new UserControl in MainWindow.xaml, the Button in the UserControl is cropped in the designer instead of being resized to fit, why is that ?
Here is the MainWindow.xaml body :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="8*" />
</Grid.ColumnDefinitions>
<controls:SearchBox Grid.Column="0"/>
</Grid>
And here is the body of the custom control :
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox
Grid.Row="0"
VerticalAlignment="Center"
Text="Search"
TextBlock.FontStyle="Italic"
TextBlock.TextAlignment="Left"
/>
<!-- Content="{StaticResource FilterLogo}" -->
<Button
Grid.Column="1"
Content="Filter"
VerticalAlignment="Center"
HorizontalAlignment="Stretch">
</Button>
<ListBox
Grid.Row="1"
Grid.ColumnSpan="2"
ItemsSource="{Binding DataContext}"
SelectedItem="{Binding DataContext}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
I don't really know why my control is cropped to be honest. Any lead please ?
Short answer: it doesn't fit.
You have two columns in your main window. Since you have not specified which column to place the UserControl, it defaults to the first column. But your Width definitions force that column to be one fourth the size of the second column.
Your SearchBox simply doesn't fit in the space you have allotted to it.
If you remove the star (*) from this line:
<ColumnDefinition Width="8*" />
...it will fit without being cropped. (Alternatively, you could place the user control in the second column, or expand the main window, or shrink the width of your UserControl.)
When using stars in the column and row definitions, use them like percentages. Like this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*" /> <!-- 10% -->
<ColumnDefinition Width=".9*" /> <!-- 90% -->
</Grid.ColumnDefinitions>
This is what the XAML reader interpreted from your usage:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" /> <!-- 800% -->
<ColumnDefinition Width="*" /> <!-- 100% -->
</Grid.ColumnDefinitions>
This will have undesired results.

Adjust TextBlock on a Button within a Grid

I have two buttons on a grid. On the right button there should be some text shown left aligned and another text right aligned. In all my tries so far the two strings are positioned in the center of the button and not left and right.
Once this is solved I need some space between the text and the left/right borders of the button.
Who can help?
My XAML-code so far to start:
<UserControl x:Class="MyNamespace.MyClass"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="900">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button>
<TextBlock Text="left button"></TextBlock>
</Button>
<Button Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="left"></TextBlock>
<TextBlock Text="right" Grid.Column="1"></TextBlock>
</Grid>
</Button>
</Grid>
</UserControl>
DonĀ“t blame me for not putting this stuff in a ResourceDictionary. Just wanted to make the example simple.
You need to add HorizontalContentAlignment="Stretch" to Button in order for contents to take up full space. After that, to make space between text and button borders, just add two more grid columns at first and last position.
XAML:
<UserControl x:Class="MyNamespace.MyClass"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="900">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button>
<TextBlock Text="left button"></TextBlock>
</Button>
<Button Grid.Column="1" HorizontalContentAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<TextBlock Text="left" Grid.Column="1"></TextBlock>
<TextBlock Text="right" Grid.Column="3"></TextBlock>
</Grid>
</Button>
</Grid>

Resources