What would be the best/right way to have a set of DataGrid columns have proportional width (Width=\"\\*\"), but to have their minimum
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:
...
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
{
///
/// 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.
///
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);
}
}
}
}