当DataGrid嵌套在分组的DataGrid中时,相对列宽不起作用 [英] Relative Column Widths Not Working When DataGrid is Nested Inside A Grouped DataGrid

查看:41
本文介绍了当DataGrid嵌套在分组的DataGrid中时,相对列宽不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个具有6个属性的对象:

Suppose I have an object with 6 attributes:

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中显示这些对象的集合:

I display a collection of these objects in a 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分组...

I populate my Grid like this, grouping by "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 :

I style my GroupItems to show a nested DataGrid within an expander:

<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列的宽度设置为自动 ...,效果很好:

With my nested DataGrid Column widths set to "Auto"... it works great:

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

The problem is when I try to use relative widths...

<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>

现在看起来像这样...

Now it looks like this...

不仅这些列超级皮包骨头,而且不是像往常一样,可以用鼠标调整大小。

Not only are the columns super skinny... they are not re-sizable with the mouse, as usual.

这个问题确实让我感到困惑。我已经搜索过SO,并尝试了一些有点运气的问题。

This issue really has me puzzled. I've searched SO and tried several somewhat-related issues without any luck.

如何设置嵌套DataGrid上的列以使用相对宽度?

How can I set the columns on my nested DataGrid to use relative widths?

推荐答案

我认为问题是WPF不知道DockPanel有多宽,所以您会得到那些细小的列。

I think the problem is that WPF doesn't know how wide the DockPanel is so you get those skinny columns.

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

One solution is to set the width of the DockPanel (or the DataGrid) to a fixed width like 500 pixels.

另一种解决方案是将DataGrid的宽度绑定到DockPanel的ActualWidth。此方法有效,但DataGrid只会增大大小,而当窗口变小时不会缩小。

Another solution is to bind the Width of the DataGrid to the ActualWidth of the DockPanel. This works but the DataGrid will only grow in size, it will not shrink when the window gets smaller.

<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似乎可行(但是idk为什么3 ...)。如果添加填充或边距,则可能需要更改这3个。要将此绑定到绑定中,我们需要一个IValueConverter。

Yet another solution is to bind the Width of the DockPanel to the ActualWidth of the Expander. The problem with this is that it doesn't work right... the Expander gets bigger because the DockPanel gets bigger and we get into a loop. What we really want is the ActualWidth of the Expander minus enough to not cause the Expander to increase it's width. I've experimented a bit and "ActualWidth - 3" seems like it works (but idk why 3...). If you add Paddings or Margins, this 3 may need to change. To get this into a binding, we need an 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();
    }
}

您需要将转换器添加为资源(应用程序或窗口或其他):

You'll need to add the converter as a resource (app or Window or whatever):

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

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

And, of course, you'll need the binding applied to the Width of the DockPanel:

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

这不是一个完美的解决方案,但可能会有所帮助吗?此方法的替代版本可以使用MultiBinding。传入扩展器的ActualWidth和DockPanel的Margin:ActualWidth-Margin.Left-Margin.Right-3(我仍然想知道为什么3?在其他人的计算机上也为3吗?)。

It's not a perfect solution but maybe it'll be helpful? An alternative version of this method could use a MultiBinding; passing in the Expander's ActualWidth and the DockPanel's Margin: ActualWidth - Margin.Left - Margin.Right - 3 (I'm still wondering why 3? And will it be 3 on everyone else's computer too?).

这篇关于当DataGrid嵌套在分组的DataGrid中时,相对列宽不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆