WPF - DataGrid Column with Width=“*”, but MinWidth to Fit Contents

前端 未结 5 1107
余生分开走
余生分开走 2020-12-09 07:48

What would be the best/right way to have a set of DataGrid columns have proportional width (Width=\"\\*\"), but to have their minimum

相关标签:
5条回答
  • 2020-12-09 08:34

    I know its a bit late, but I found your question and programmed a pure-XAML solution.

     <ColumnDefinition Width="42*" MinWidth="{Binding Path=ActualWidth, ElementName=projectInfoHeader }"/> 
    

    Where the ElementName points to the control taking up most of the space. Of course thats only possible to do with elements, that do have a limited width. If you do it for example for a GroupBox, than you can resize only to larger width and never resize to smaller one.

    If you have several candidates for the value of MinWidth, you need to write yourself a IMultiValueConverter, which takes an object[], parses it to floats, and returns the maximum (its just 1 linq query if you use it only yourselves and don't need to handle bad usage of the converter)

    This way also supports dynamic changing of the MinWidth.

    0 讨论(0)
  • 2020-12-09 08:43

    I also had problems to size Grid columns correctly inside the GridViewColumn. There were several things that I tried but then I found the UniformGrid. It was the ultimate solution for me. It just works. I haven't knew it before...seems that it doesn't exist in VS toolbox by default (?) and thus didn't know it even exists.

    You can find more about UniformGrid from here.

    0 讨论(0)
  • 2020-12-09 08:45

    Give the column a name in the XAML:

    <Grid>
          <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="*" Name="Col1"/>
                 <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>
    </Grid>
    

    Then set the MinWidth property in the code as shown below:

    public MainWindow()
    {
        InitializeComponent();
    
        Col1.MinWidth = 340; //enter desired minimum width here
    }
    
    0 讨论(0)
  • 2020-12-09 08:48

    You can create a dependency property (called e.g. HorizontalPropFillOfBlankSpace) for Grid control which will ensure what you need (columns with Width="*", but MinWidth to fit contents). Then you can apply it on any grid you want:

    <Grid namespace:GridHelper.HorizontalPropFillOfBlankSpace="True">
       <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto" />
          <ColumnDefinition Width="Auto" />
       </Grid.ColumnDefinitions>
       ...
    

    You can see an example of the implementation of this dependency property below. Only columns with Width="Auto" are automatically resized to fill gap space. It can be customized by you what you need.

    public class GridHelper
    {
       /// <summary>
       /// Columns are resized to proportionally fill horizontal blank space.
       /// It is applied only on columns with the Width property set to "Auto".
       /// Minimum width of columns is defined by their content.
       /// </summary>
       public static readonly DependencyProperty HorizontalPropFillOfBlankSpaceProperty =
          DependencyProperty.RegisterAttached("HorizontalPropFillOfBlankSpace", typeof(bool), typeof(GridHelper), new UIPropertyMetadata(false, OnHorizontalPropFillChanged));
    
       public static bool GetHorizontalPropFillOfBlankSpace(Grid grid)
          => (bool)grid.GetValue(HorizontalPropFillOfBlankSpaceProperty);
    
       public static void SetHorizontalPropFillOfBlankSpace(Grid grid, bool value)
          => grid.SetValue(HorizontalPropFillOfBlankSpaceProperty, value);
    
       private static void OnHorizontalPropFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       {
          if (!(d is Grid grid))
             return;
    
          if ((bool)e.NewValue)
          {
             grid.Loaded += Grid_Loaded;
          }
          else
          {
             grid.Loaded -= Grid_Loaded;
          }
       }
    
       private static void Grid_Loaded(object sender, RoutedEventArgs e)
       {
          if (!(sender is Grid grid))
             return;
    
          foreach (var cd in grid.ColumnDefinitions)
          {
             if (cd.Width.IsAuto && cd.ActualWidth != 0d)
             {
                if (cd.MinWidth == 0d)
                   cd.MinWidth = cd.ActualWidth;
                cd.Width = new GridLength(1d, GridUnitType.Star);
             }
          }
       }
    }
    
    0 讨论(0)
  • 2020-12-09 08:49

    Set Width = "Auto" in XAML.

    Then in the code:

    MinWidth = ActualWidth
    Width = new GridLength(1, GridUnitType.Star)
    
    0 讨论(0)
提交回复
热议问题