Изменение размера загружаемого столбца DataGrid программно

#c# #wpf #datagrid #column-width

#c# #wpf #datagrid #ширина столбца

Вопрос:

У меня есть эта DataGrid, которая выглядит следующим образом, когда я загружаю данные в первый раз: введите описание изображения здесь

итак, это почти идеально, но то, что я действительно хочу, отображается при максимальном изменении размера окна — столбцы теперь расположены следующим образом: введите описание изображения здесь

Я хотел бы расположить самые правые столбцы в правой части представления DataGrid, а в левом столбце выделить остальную часть представления.

Мой вопрос: могу ли я вызвать событие в DataGrid, чтобы вызвать такое расположение столбцов, которое в противном случае происходило бы только при максимальном увеличении окна?

Упрощенная версия XAML DataGrid выглядит следующим образом:

 <DataGrid
   ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}}"
   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
   ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
   ScrollViewer.VerticalScrollBarVisibility="Auto" 
   ScrollViewer.CanContentScroll="True"
   AutoGenerateColumns="False"
   GridLinesVisibility="None"
   ColumnWidth="*">
   <DataGrid.Columns>
       <DataGridTemplateColumn Width="*" Header="Name">
           <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                   <Grid>
                       <Grid.ColumnDefinitions>
                           <ColumnDefinition Width="Auto"/>
                           <ColumnDefinition Width="*"/>
                       </Grid.ColumnDefinitions>

                       <TextBlock Grid.Column="1"
                                  Text="{Binding ItemName}"
                                  ToolTipService.ShowOnDisabled="true"
                                  >
                        </TextBlock>
                   </Grid>
               </DataTemplate>
           </DataGridTemplateColumn.CellTemplate>
       </DataGridTemplateColumn>
       <DataGridTemplateColumn Width="Auto" Header="Size">
           <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                   <TextBlock
                       Text="{Binding ItemLengthA}"
                              HorizontalAlignment="Right"
                              Margin="3,0,0,0"
                   />
               </DataTemplate>
           </DataGridTemplateColumn.CellTemplate>
       </DataGridTemplateColumn>
       <DataGridTemplateColumn Width="Auto" Header="Modified">
           <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                   <TextBlock
                       Text="{Binding ItemLastUpdateA}"
                       HorizontalAlignment="Right"
                       Margin="3,0,0,0"
                   />
               </DataTemplate>
           </DataGridTemplateColumn.CellTemplate>
       </DataGridTemplateColumn>
   </DataGrid.Columns>
</DataGrid>
  

У меня также есть рабочее приложение / элемент управления для проверки здесь, но я думаю, что просмотра приведенного выше XAML должно быть достаточно, чтобы найти решение, основанное на заданном макете.

Комментарии:

1. Мне кажется, что с кодом все в порядке. Я тестировал аналогичное DataGrid с некоторыми данными, оно просто продолжает отображаться как ваше второе изображение, независимо от того, как был изменен размер. Так что, возможно, на макет повлияла какая-то другая вещь.

2. Вы размещаете свою сетку данных внутри окна с SizeToContent =»WidthAndHeight» или SizeToContent = «Width»? Я столкнулся с подобным поведением, когда окно адаптируется к ширине содержимого.

3. Код окна — это просто стандартный код, который вы получите, если создадите новый проект WPF — никаких особых вещей там нет. Есть некоторые другие функции, такие как синхронизация прокрутки и настройка цвета фона в стиле строк, которые я могу попытаться отключить, чтобы посмотреть, изменится ли поведение, но до сих пор я не думал, что это будет иметь значение… Я проверю, изменяет ли отключение поведение ширины столбца…

Ответ №1:

Я попытался воспроизвести ваш случай и пришел к результату: это зависит от того, как вы будете использовать ItemsSource. В случае, если ItemsSource в ViewModel представляет собой список, тогда вы можете просто назначить ему новый экземпляр и вызвать событие PropertyChanged. Это приведет к тому, что столбцы будут вести себя так, как вы хотите (Width=»Auto»).

       ItemsSource = new List<Data>();
      // ItemsSource.Add(new Data()); // ..adding data 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemsSource)));
  

Однако, поскольку в настоящее время это не работает, я предполагаю, что у вас, возможно, есть ObservableCollection в качестве ItemsSource, и вы добавляете элементы туда. В моих тестах он ведет себя так, как вы описали, столбцы остаются маленькими, если не изменять размер окна или столбцов вручную.

   public ObservableCollection<Data> ItemsSource { get; set; }
  public void AddItems()
  {
      ItemsSource.Add(new Data()); // not working
  }
  

Единственный способ, который я нашел, чтобы заставить сетку сделать это, заключался в том, чтобы изменить ширину столбца с Auto на некоторое значение, а затем обратно. Для этого используется кнопка. но любая загрузка также будет работать

     private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach (DataGridTemplateColumn item in MyDataGrid.Columns)
        {
            if (item.Width.IsAuto)
            {
                item.Width = new DataGridLength(item.ActualWidth, item.Width.UnitType);
                item.Width = DataGridLength.Auto;
            }
        }
    }
  

Комментарии:

1. Я могу проверить ваши выводы — я также могу воспроизвести то же самое требуемое поведение с ObservableCollection<> — похоже, дело не в типе коллекции, а в том факте, что существующая коллекция действительно заменяется новой коллекцией, за которой следует событие PropertyChanged, которое заставляет это работать. ObservableCollection фактически отправляет NotifyCollectionChangedAction. Сброс, но это, по-видимому, недостаточно разумно для того, чтобы Сетка действительно правильно распределяла элементы. Итак, решение теперь состоит в том, чтобы всегда восстанавливать всю (наблюдаемую) коллекцию при каждой перезагрузке … спасибо за подсказку 🙂