当DataGrid嵌套在分组的DataGrid中时,相对列宽度无法正常工作。

6
假设我有一个具有6个属性的对象:
public class MyClass
{
    public string Attribute1 { get; set; }
    public string Attribute2 { get; set; }
    public string Attribute3 { get; set; }
    public string Attribute4 { get; set; }
    public string Attribute5 { get; set; }
    public string Attribute6 { get; set; }
}

我在 DataGrid 中显示了这些对象的集合:

<Grid>
    <DataGrid x:Name="myGrid" Margin="5, 5, 5, 5" AutoGenerateColumns="False" CanUserAddRows="False" IsReadOnly="True">
        <DataGrid.GroupStyle>
            <GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
                <GroupStyle.Panel>
                    <ItemsPanelTemplate>
                        <DataGridRowsPresenter/>
                    </ItemsPanelTemplate>
                </GroupStyle.Panel>
            </GroupStyle>
        </DataGrid.GroupStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Attribute1" Binding="{Binding Attribute1}" Width="5*"/>
            <DataGridTextColumn Header="Attribute2" Binding="{Binding Attribute2}" Width="5*"/>
            <DataGridTextColumn Header="Attribute3" Binding="{Binding Attribute3}" Width="10*"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

我这样填充我的Grid,按“Attribute1”分组...
    public MainWindow()
    {
        InitializeComponent();

        ObservableCollection<MyClass> data = new ObservableCollection<MyClass>();
        data.Add(new MyClass { Attribute1 = "Red", Attribute4 = "Circle", Attribute5 = "Large", Attribute6 = "Transparent" });
        data.Add(new MyClass { Attribute1 = "Red", Attribute4 = "Square", Attribute5 = "Medium", Attribute6 = "Opaque" });
        data.Add(new MyClass { Attribute1 = "Red", Attribute4 = "Triangle", Attribute5 = "Large", Attribute6 = "Opaque" });
        data.Add(new MyClass { Attribute1 = "Yellow", Attribute4 = "Square", Attribute5 = "Large", Attribute6 = "Transparent" });
        data.Add(new MyClass { Attribute1 = "Blue", Attribute4 = "Triangle", Attribute5 = "Small", Attribute6 = "Transparent" });
        data.Add(new MyClass { Attribute1 = "Blue", Attribute4 = "Sphere", Attribute5 = "Small", Attribute6 = "Opaque" });


        ListCollectionView lcv = new ListCollectionView(data);
        lcv.GroupDescriptions.Add(new PropertyGroupDescription("Attribute1"));
        myGrid.ItemsSource = lcv;

    }

我将我的GroupItems样式设置为在展开器中显示嵌套的DataGrid:

<Window.Resources>
    <Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Expander x:Name="exp" IsExpanded="True" Foreground="Black">
                        <Expander.Header>
                                <TextBlock Foreground="Black" Text="{Binding Name}"/>
                        </Expander.Header>
                        <DockPanel>
                            <DataGrid ItemsSource="{Binding Items}" x:Name="subGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserAddRows="False">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="Attribute 4" Binding="{Binding Attribute4}" Width="Auto"/>
                                    <DataGridTextColumn Header="Attribute 5" Binding="{Binding Attribute5}" Width="Auto"/>
                                    <DataGridTextColumn Header="Attribute 6" Binding="{Binding Attribute6}" Width="Auto"/>
                                </DataGrid.Columns>
                            </DataGrid>
                        </DockPanel>
                    </Expander>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

如果我将嵌套的DataGrid列宽设置为“自动”……它非常出色:

enter image description here

问题是当我尝试使用相对宽度时……

<DataGrid ItemsSource="{Binding Items}" x:Name="subGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Attribute 4" Binding="{Binding Attribute4}" Width="1*"/>
        <DataGridTextColumn Header="Attribute 5" Binding="{Binding Attribute5}" Width="1*"/>
        <DataGridTextColumn Header="Attribute 6" Binding="{Binding Attribute6}" Width="2*"/>
    </DataGrid.Columns>
</DataGrid>

现在它看起来是这样的... 输入图像描述 这些列不仅非常窄...而且不能像通常那样用鼠标改变大小。
这个问题真的让我感到困惑。我在SO上搜索了一下,并尝试了几个相关问题,但没有找到任何解决方法。
如何设置嵌套DataGrid上的列使用相对宽度?
1个回答

5
我认为问题在于WPF不知道DockPanel有多宽,所以你会得到那些细窄的列。
一种解决方案是将DockPanel(或DataGrid)的宽度设置为固定宽度,例如500像素。
另一种解决方案是将DataGrid的宽度绑定到DockPanel的ActualWidth。这个方法可行,但是当窗口变小时,DataGrid只会增长大小,而不会缩小。
<DataGrid ItemsSource="{Binding Items}" 
          x:Name="subGrid" 
          AutoGenerateColumns="False" 
          IsReadOnly="True" 
          CanUserAddRows="False" 
          Width="{Binding 
                  RelativeSource={RelativeSource AncestorType=DockPanel}, Path=ActualWidth}">

另一种解决方法是将DockPanel的宽度绑定到Expander的ActualWidth上。但问题是它并不能正常工作...... Expander变大是因为DockPanel变大,我们进入了一个循环。实际上,我们想要的是Expander的ActualWidth减去足够的值,以避免Expander增加宽度。我做了一些尝试,发现"ActualWidth - 3"似乎可以解决问题(但我不知道为什么是3...)。如果添加了Padding或Margin,则可能需要更改此值。为了将其绑定,我们需要使用IValueConverter。
public class ActualWidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is double)
            return (double)value - 3;
        return value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

您需要将转换器作为资源添加到应用程序或窗口中:

<Window ....
    xmlns:app="clr-namespace:WpfApplication25">
<Window.Resources>
    <app:ActualWidthConverter x:Key="ActualWidthConverter" />
</Window.Resources>

当然,您需要将绑定应用到DockPanel的宽度:

<DockPanel Width="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=ActualWidth, Converter={StaticResource ActualWidthConverter}}">

这可能不是完美的解决方案,但也许会有所帮助?该方法的另一种替代版本可以使用 MultiBinding。将 Expander 的 ActualWidth 和 DockPanel 的 Margin 传递进去:ActualWidth - Margin.Left - Margin.Right - 3(我仍在想为什么是3?而且它在别人的电脑上也是3吗?)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接