【问题标题】:Relative Column Widths Not Working When DataGrid is Nested Inside A Grouped DataGrid当 DataGrid 嵌套在分组 DataGrid 中时,相对列宽不起作用
【发布时间】:2015-04-22 17:40:48
【问题描述】:

假设我有一个具有 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>

我像这样填充我的网格,按“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 列宽设置为“自动”...效果很好:

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

<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 上的列设置为使用相对宽度?

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    我认为问题在于 WPF 不知道 DockPanel 的宽度,因此您会得到那些细小的列。

    一种解决方案是将 DockPanel(或 DataGrid)的宽度设置为固定宽度,例如 500 像素。

    另一种解决方案是将 DataGrid 的 Width 绑定到 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 的 Width 绑定到 Expander 的 ActualWidth。这样做的问题是它不能正常工作...... Expander 变大了,因为 DockPanel 变大了,我们进入了一个循环。我们真正想要的是 Expander 的 ActualWidth 减去足以不导致 Expander 增加它的宽度。我进行了一些实验,“ActualWidth - 3”似乎有效(但我知道为什么 3 ...)。如果添加 Paddings 或 Margins,这 3 可能需要更改。要将其放入绑定中,我们需要一个 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 吗?)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 2011-05-10
      • 1970-01-01
      • 2019-04-01
      相关资源
      最近更新 更多