WPF UserControl 组件网格定义问题

WPF UserControl component grid definition issue

我有两列的简单用户控件,在第一列我有 DataGrid:

<UserControl x:Class="Caliburn_SimpleInjector_Sample.ViewModel.ShellView"
             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"
             MinWidth="1100" MinHeight="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=".20*" />
            <ColumnDefinition Width="5" />
            <ColumnDefinition Width=".70*" />
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=Tasks, Mode=OneWay}"
                  SelectedItem="{Binding SelectedTask}"
                  AutoGenerateColumns="False" IsReadOnly="True"
                  CanUserResizeRows="False" GridLinesVisibility="None"
                  SelectionUnit="FullRow"
                  RowHeaderWidth="0"
                  FontSize="14">
            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="BorderThickness" Value="0" />
                    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                </Style>
            </DataGrid.CellStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Col 1" Binding="{Binding Find}" />
                <DataGridTextColumn Header="Col 2" Binding="{Binding Action}" />
                <DataGridTextColumn Header="Col 3" Binding="{Binding Status}" />
            </DataGrid.Columns>
        </DataGrid>

        <GridSplitter Grid.Row="0" Grid.Column="1"
                      VerticalAlignment="Stretch"
                      ResizeBehavior="PreviousAndNext"
                      Width="5" Background="#FFBCBCBC" />

        <StackPanel Grid.Row="0" Grid.Column="2" Background="Red"></StackPanel>
    </Grid>
</UserControl>

让我们来看看我们有什么:

完美!这正是我需要的。

但是!如果我只是尝试为 DataGrid 内的每一列设置动态 Width,整个模板就会损坏:

<DataGrid.Columns>
    <DataGridTextColumn Width="0.2*" Header="Col 1 20%" Binding="{Binding Find}" />
    <DataGridTextColumn Width="0.2*" Header="Col 2 20%" Binding="{Binding Action}" />
    <DataGridTextColumn Width="0.6*" Header="Col 3 60%" Binding="{Binding Status}" />
</DataGrid.Columns>

结果如下:

还有一件有趣的事。如果您尝试开始调整 window 的大小 - 那么一切都会变得正常,例如: ScreenCast

有人可以帮我解决这个问题吗?

提前致谢。

您尝试过将 MinWidth 和 Width 与 * 组合使用吗?请参见下面的示例:

<DataGrid.Columns>
<DataGridTextColumn MinWidth="0.2" Width="*" Header="Col 1 20%" Binding="{Binding Find}" />
<DataGridTextColumn MinWidth="0.2" Width="*" Header="Col 2 20%" Binding="{Binding Action}" />
<DataGridTextColumn MinWidth="0.6" Width="*" Header="Col 3 60%" Binding="{Binding Status}" /></DataGrid.Columns>

只需设置控件window宽高

<UserControl x:Class="Caliburn_SimpleInjector_Sample.ViewModel.ShellView"
             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"
             MinWidth="1100" MinHeight="400"
             Width="1100" Height="400"
             >

控件将完美运行

问题在于空的StackPanel。您正在使用 * 表示动态 DataGridTextColumn 宽度。

  • (star) 占用任何可用的剩余 space

详细讨论如下: Meaning of * (asterisk) in a WPF ColumnDefinition? (weighted proportion of available space)

只需用控件填充 StackPanel,或者为了获得灵感,将 StackPanel 替换为 DataGrid 定义的副本。作为示例演示将是这样的:

    <UserControl x:Class="Caliburn_SimpleInjector_Sample.ViewModel.ShellView"
             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"
             MinWidth="1100" MinHeight="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=".20*" />
            <ColumnDefinition Width="5" />
            <ColumnDefinition Width=".70*" />
        </Grid.ColumnDefinitions>
        <DataGrid Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=Tasks, Mode=OneWay}"
                  SelectedItem="{Binding SelectedTask}"
                  AutoGenerateColumns="False" IsReadOnly="True"
                  CanUserResizeRows="False" GridLinesVisibility="None"
                  SelectionUnit="FullRow"
                  RowHeaderWidth="0"
                  FontSize="14">
            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="BorderThickness" Value="0" />
                    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                </Style>
            </DataGrid.CellStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Width="0.2*" Header="Col 1 20%" Binding="{Binding Find}" />
                <DataGridTextColumn Width="0.2*" Header="Col 2 20%" Binding="{Binding Action}" />
                <DataGridTextColumn Width="0.6*" Header="Col 3 60%" Binding="{Binding Status}" />
            </DataGrid.Columns>
        </DataGrid>

        <GridSplitter Grid.Row="0" Grid.Column="1"
                      VerticalAlignment="Stretch"
                      ResizeBehavior="PreviousAndNext"
                      Width="5" Background="#FFBCBCBC" />

        <DataGrid Grid.Row="0" Grid.Column="2" ItemsSource="{Binding Path=Tasks, Mode=OneWay}"
                  SelectedItem="{Binding SelectedTask}"
                  AutoGenerateColumns="False" IsReadOnly="True"
                  CanUserResizeRows="False" GridLinesVisibility="None"
                  SelectionUnit="FullRow"
                  RowHeaderWidth="0"
                  FontSize="14">
            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Setter Property="BorderThickness" Value="0" />
                    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                </Style>
            </DataGrid.CellStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Width="0.2*" Header="Col 1 20%" Binding="{Binding Find}" />
                <DataGridTextColumn Width="0.2*" Header="Col 2 20%" Binding="{Binding Action}" />
                <DataGridTextColumn Width="0.6*" Header="Col 3 60%" Binding="{Binding Status}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

然后您可以观察到控件的行为是正确的,因为没有 space 剩下的数据可供第一个数据网格列使用。

问题与 Caliburn 无关。与此处描述的问题完全相同:Window SizeToContent issue when child UserControl has grid with Column of max Width.

我按照此处建议的方式解决了我的问题:fix