Binding.Converter к Visible DataGridTextColumn

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

Необходимо прибиндить конвертор к DataGridTextColumn.

DataGrid.ItemsSource прикреплен к:

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

(в прикрепленно ViewModel соответственно)

XAML:

xmlns:converter="clr-namespace:appSend.Controllers.Converter"

<Page.Resources>
        <converter:TableColumnVisibilityConverter x:Key="VisibilityConverter"/>
</Page.Resources>

<DataGrid ItemsSource="{Binding DataTable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="Номер дела" Binding="{Binding Path=CaseNumber}"
                                                    Visibility="{Binding Path=ItemsSource, RelativeSource={RelativeSource AncestorType=DataGrid}, Converter={StaticResource VisibilityConverter}, ConverterParameter=CaseNumber}"/>
                                <DataGridTextColumn Header="Короткое имя" Binding="{Binding Path=ShortName}"
                                                    Visibility="{Binding Path=ItemsSource, RelativeSource={RelativeSource AncestorType=DataGrid}, Converter={StaticResource VisibilityConverter}, ConverterParameter=ShortName}"/>
                            </DataGrid.Columns>
                        </DataGrid>

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

Converter:

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.Hidden;
            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.Hidden;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
    }

Ответы

▲ 1Принят

Проблема в том, что DataGridTextColumn не является частью визуального дерева и привязки на ней в принципе не работают. Единственное, что с этими привязками работает - это ресурсы StaticResource.

Через конвертер мне победить не удалось. Но если задача сводится к управлению видимостью колонок, то можно сделать это через вьюмодель для них.

Использую код из прошлого вопроса и делаю вот такую вьюмодель

public class AppealColumnViewModel : NotifyPropertyChanged
{
    private bool caseNumber = true;
    private bool shortName = true;
    private bool file = true;
    private bool text = true;
    private bool courtRegion = true;
    private bool courtNumber = true;
    private bool fileExist = true;
    private bool done = true;
    private bool enforcementProceedingsNumber = true;
    private bool enforcementProceedingsId = true;
    private bool osp = true;
    private bool copyrightHolderName = true;
    private bool clientName = true;
    private bool courtName = true;

    public bool CaseNumber { get => caseNumber; set => Set(ref caseNumber, value); }
    public bool ShortName { get => shortName; set => Set(ref shortName, value); }
    public bool File { get => file; set => Set(ref file, value); }
    public bool Text { get => text; set => Set(ref text, value); }
    public bool CourtRegion { get => courtRegion; set => Set(ref courtRegion, value); }
    public bool CourtNumber { get => courtNumber; set => Set(ref courtNumber, value); }
    public bool FileExist { get => fileExist; set => Set(ref fileExist, value); }
    public bool Done { get => done; set => Set(ref done, value); }
    public bool EnforcementProceedingsNumber { get => enforcementProceedingsNumber; set => Set(ref enforcementProceedingsNumber, value); }
    public bool EnforcementProceedingsId { get => enforcementProceedingsId; set => Set(ref enforcementProceedingsId, value); }
    public bool Osp { get => osp; set => Set(ref osp, value); }
    public bool CopyrightHolderName { get => copyrightHolderName; set => Set(ref copyrightHolderName, value); }
    public bool ClientName { get => clientName; set => Set(ref clientName, value); }
    public bool CourtName { get => courtName; set => Set(ref courtName, value); }
}

В основную вьюмодель заношу свойство

public AppealColumnViewModel ColumnsState { get; } = new();

Далее создаю класс для ресурса-прокси

public class BindingProxy : Freezable
{
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(object), typeof(BindingProxy));

    protected override Freezable CreateInstanceCore() => new BindingProxy();

    public object Value
    {
        get => GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }
}

Далее вношу это в ресурсы DataGrid

<DataGrid.Resources>
    <local:BindingProxy x:Key="ColumnsState" Value="{Binding ColumnsState}"/>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</DataGrid.Resources>

И делаю вот такую привязку

<DataGridTextColumn Header="Номер дела" Binding="{Binding CaseNumber}"
                    Visibility="{Binding Value.CaseNumber, Source={StaticResource ColumnsState}, Converter={StaticResource BooleanToVisibilityConverter}}"/>

Теперь можно делать вкл и выкл колонки просто задав

ColumnsState.CaseNumber = false;