Relative Column Widths Not Working When DataGrid is Nested Inside A Grouped DataGrid

前端 未结 1 1321
终归单人心
终归单人心 2021-01-19 02:56

Suppose I have an object with 6 attributes:

public class MyClass
{
    public string Attribute1 { get; set; }
    public string Attribute2 { get; set; }
             


        
相关标签:
1条回答
  • 2021-01-19 03:34

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

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

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

    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>
    

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

    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?).

    0 讨论(0)
提交回复
热议问题