I have a seemingly simple use case but its been troubling me for hours
I have a grid with two rows and two columns, the first column should take all the available width and the second column should take the width it requires. The problem is with the 'required width' of the second column. This column contains a datagrid in the top row and a label (for simplicity) in the bottom row. The datagrid has two columns which should both take up 50% width of the datagrid.
I want:
The problem:
The code:
x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid Grid.Column="1" Name="grid">
<!-- Change column width to simulate the problemn-->
<DataGrid ItemsSource="{Binding Items}" ColumnWidth="*" RowHeaderWidth="0" Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}"/>
</Grid>
<!-- change label text to simulate problemn-->
<Label Grid.Row="1" Grid.Column="1" Content="x"/>
</Grid>
This is dirty and would probably cause me to rethink my design, but it works based on your requirements. I'm not sure how else to achieve this without creating a custom control or greatly modifying the DataGrid
default template, but here goes.
Change your DataGrid
styling to this and give names to both the Label
and the DataGrid
.
<DataGrid Name="dg" ItemsSource="{Binding Items}" CanUserResizeColumns="False"/>
///
<Label Grid.Row="1" Grid.Column="1" Content="x" Name="label"/>
Then create a ContentRendered
event for your MainWindow
.
Title="MainWindow" Height="450" Width="800" Name="mw" ContentRendered="Mw_ContentRendered">
Now in the render event, manually resize columns after the render occurs. You can't assign a star to the width as it won't resize correctly, so you need to divide your widths evenly base on column count.
private void Mw_ContentRendered(object sender, EventArgs e)
{
//Loop through columns and resize
for (int x = 0; x < dg.Columns.Count; x++)
{
double div = dg.ActualWidth / dg.Columns.Count;
double add = div - dg.Columns[x].ActualWidth;
if (add < 0) { div += -add; }
dg.Columns[x].Width = new DataGridLength(div);
}
}
EDIT: Updated width logic to account for uneven widths
I ended up creating my own user control.
This was relatively easy as I know at design time which rows I will have in the 'datagridview'.
Tronald's suggestion works, provided that the data does not change after rendering (mine does, both the datagrid contents and the 'label' change based on selections made in the rest of the application).
I still think that the 'Width="*" MinWidth="auto"' combination should be possible for a datagrid so If anybody has a solution.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.