WPF - Столбец DataGrid с шириной ="*", но минимальной шириной, чтобы соответствовать содержимому

Что было бы лучшим / правильным способом иметь набор DataGrid столбцы имеют пропорциональную ширину (Width="\*"), но чтобы их минимальная ширина была как минимум шириной их содержимого? На данный момент, если я использую Width="*", тогда столбцы остаются точно пропорциональными, но содержимое обрезается, если столбцы становятся слишком тонкими. Если я использую Width="Auto"тогда столбцы сами по размеру соответствуют своему содержанию, но это делает их всех разных размеров.

То, что я хочу, это действительно сочетание двух, как Width="\*", MinWidth="Auto" так что, когда есть дополнительная ширина, все столбцы будут разнесены до одинаковой ширины, но когда сетка станет меньше, содержимое никогда не будет обрезано.

К сожалению, MinWidth="Auto" не существует, поэтому я думаю, мне нужно связать столбец MinWidth собственности, но трудно точно понять, к чему я бы это привязал.

Как мне сказать WPF "MinWidth=" ширина самого широкого столбца контента?

4 ответа

Я знаю, что уже поздно, но я нашел ваш вопрос и запрограммировал решение на чистом XAML.

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

Где ElementName указывает на контроль, занимающий большую часть пространства. Конечно, это возможно только с элементами, которые имеют ограниченную ширину. Если вы делаете это, например, для GroupBox, чем вы можете изменить размер только на большую ширину и никогда не изменять размер на меньшую.

Если у вас есть несколько кандидатов на значение MinWidth, вам нужно написать себе IMultiValueConverter, который берет объект [], анализирует его до числа с плавающей запятой и возвращает максимум (это всего лишь 1 запрос linq, если вы используете его только сами и не должны обрабатывать неправильное использование конвертера)

Этот способ также поддерживает динамическое изменение MinWidth,

Задавать Width = "Auto" в XAML.

Тогда в коде:

MinWidth = ActualWidth
Width = new GridLength(1, GridUnitType.Star)

У меня также были проблемы с правильным размером столбцов Grid внутри GridViewColumn. Я попробовал несколько вещей, но потом нашел UniformGrid. Это было окончательное решение для меня. Это просто работает. Я не знал этого раньше... кажется, что он не существует в VS toolbox по умолчанию (?) И, следовательно, не знал, что он даже существует.

Вы можете найти больше о UniformGrid здесь.

Дайте столбцу имя в XAML:

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

Затем установите MinWidth свойство в коде, как показано ниже:

public MainWindow()
{
    InitializeComponent();

    Col1.MinWidth = 340; //enter desired minimum width here
}

Вы можете создать свойство зависимости (называемое, например, HorizontalPropFillOfBlankSpace) для элемента управления Grid, который обеспечит то, что вам нужно (столбцы с Width="*", но MinWidth, чтобы соответствовать содержимому). Затем вы можете применить его к любой сетке:

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

Вы можете увидеть пример реализации этого свойства зависимости ниже. Только столбцы с Width="Auto"автоматически изменяются, чтобы заполнить пробел. Вы можете настроить то, что вам нужно.

       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);
         }
      }
   }
}
Другие вопросы по тегам