Убрать незаполненные столбцы DataGrid Wpf MVVM

Рейтинг: 1Ответов: 1Опубликовано: 21.03.2023

Есть класс содержащий в себе много полей.

public class AppealModel
{
    public string CaseNumber { get; set; }
    public string ShortName { get; set; }
    public string File { get; set; }
    public string Text { get; set; }
    public string CourtRegion { get; set; }
    public string CourtNumber { get; set; }
    public bool FileExist { get; set; }
    public bool Done { get; set; } = false;
    public string EnforcementProceedingsNumber { get; set; }
    public string EnforcementProceedingsId { get; set; }
    public string Osp { get; set; }
    public string CopyrightHolderName { get; set; }
    public string ClientName { get; set; }
    public string CourtName { get; set; }
}

Коллекция с этим объектом подключена к DataGrid ItemSource:

ViewModel:

private ObservableCollection<AppealModel> _dataTable;
public ObservableCollection<AppealModel> DataTable
{
    get => _dataTable;
    set => Set(ref _dataTable, value);
}

XAML:

ItemsSource="{Binding DataTable}"

так же, в ручную, были подключены Data.Grid.Columns:

<DataGrid.Columns>
      <DataGridTextColumn Header="Номер дела" Binding="{Binding CaseNumber}" Visibility="Hidden"/>
      <DataGridTextColumn Header="Короткое имя" Binding="{Binding ShortName}"/>
      <DataGridTextColumn Header="Файл обращения" Binding="{Binding File}"/>
      <DataGridTextColumn Header="Текст обращения" Binding="{Binding Text}"/>
      <DataGridTextColumn Header="Регион суда" Binding="{Binding CourtRegion}"/>
      <DataGridTextColumn Header="№ Исп. пр." Binding="{Binding EnforcementProceedingsNumber}"/>
      <DataGridTextColumn Header="id Исп. пр." Binding="{Binding EnforcementProceedingsId}"/>
      <DataGridTextColumn Header="ОСП" Binding="{Binding Osp}"/>
      <DataGridTextColumn Header="Правообладатель" Binding="{Binding CopyrightHolderName}"/>
      <DataGridTextColumn Header="Клиент" Binding="{Binding ClientName}"/>
      <DataGridTextColumn Header="Суд" Binding="{Binding CourtName}"/>
</DataGrid.Columns>

Далее идет простое наполнение коллекции, но не во все столбцы! т.к. сама таблица решает разные задачи и не все данные нужны для той или иной.

Пример загруженных данных: введите сюда описание изображения

Мне нужно избавиться от пустых столбцов.

Как это сделать?

Ответы

▲ 1Принят

Решение в лоб. Прятать колонку, если там null во всех строках.

Заведите конвертер, получится немного рефлексии

public class TableColumnVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is not IEnumerable || parameter is not string propertyName || string.IsNullOrWhiteSpace(propertyName))
            return Visibility.Collapsed;
        Type type = null;
        PropertyInfo pi = null;
        foreach (object item in (IEnumerable)value)
        {
            if (type is null)
            {
                type = item.GetType();
                if (type.IsValueType)
                    return Visibility.Visible;
            }
            if (pi is null)
                pi = type.GetProperty(propertyName);
            if (pi.GetValue(item) is not null)
                return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

В данном случае ячейка будет считаться пустой, если там null.

После добавления конвертера в проект нужно пересобрать проект, и только потом переходить к редактированию XAML

Подключаю конвертер

<Window.Resources>
    <TableColumnVisibilityConverter x:Key="TableColumnVisibilityConverter"/>
</Window.Resources>

И для колонок задать Visibility

<DataGridTextColumn
    Header="Суд"
    Binding="{Binding CourtName}"
    Visibility="{Binding ItemsSource, RelativeSource={RelativeSource AncestorType=DataGrid}, Converter={StaticResource TableColumnVisibilityConverter}, ConverterParameter=CourtName}"/>

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


Данное решение доработано: Binding.Converter к Visible DataGridTextColumn