Подтвердить что ты не робот

Связывание видимости для DataGridColumn в WPF

Как скрыть столбец в WPF DataGrid через привязку?

Это то, что я сделал:

<DataGridTextColumn Header="Column header"
                    Binding="{Binding ColumnValue}"
                    Width="100"
                    ElementStyle="{StaticResource DataGridRightAlign}"
                    Visibility="{Binding MyColumnVisibility}" />

И это то, что я получил (кроме столбца все еще видны):

Ошибка System.Windows.Data: 2: Не удается найти управляющий элемент FrameworkElement или FrameworkContentElement для целевого элемента. BindingExpression: Path = MyColumnVisibility; DataItem = NULL; целевым элементом является "DataGridTextColumn" (HashCode = 1460142); target является "Видимость" (тип "Видимость" )

Не знаю, что означает. Есть ли какой-то господин президент где-то в моем окне, который решает, что работает, а что нет? Или мне нужно проголосовать за что-то?

Во время поиска в Интернете решений я нашел дюжину страниц с многообещающим названием, но совершенно несвязанным или невоспроизводимым содержимым. Так что это первый вопрос о проблеме. Любая идея?

4b9b3361

Ответ 1

Прежде всего DataGridTextColumn или любые другие поддерживаемые столбцы dataGrid не лежат в визуальном дереве DataGrid. Следовательно, по умолчанию он не наследует DataContext от DataGrid. Но он работает только для Binding DP и для другого DP на DataGridColumn.

Поскольку они не лежат в одном и том же VisualTree, поэтому любая попытка получить DataContext с помощью RelativeSource не будет работать, потому что DataGrid не сможет перейти к DataGrid.

Есть два способа добиться этого:


Первый, используя объекты Freezable - Freezable, может наследовать DataContext, даже если они не находятся в визуальном или логическом дереве. Таким образом, мы можем воспользоваться этим для нашего использования.

Сначала создайте класс, наследующий от Freezable и Data DP, который мы можем использовать для привязки в XAML:

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object),
                                     typeof(BindingProxy));
}

Теперь добавьте экземпляр из него в ресурсы DataGrid, чтобы он мог наследовать DataGrid DataContext, а затем может связываться с его Data DP:

    <DataGrid>
        <DataGrid.Resources>
            <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
                                                Source={StaticResource proxy}}"/>
        </DataGrid.Columns>
    </DataGrid>

Второй, вы можете обратиться к любому элементу пользовательского интерфейса в XAML, используя ElementName или x:Reference. Но ElementName работает только в одном визуальном дереве, тогда как x: Reference не имеет такого ограничения.

Итак, мы можем использовать это и в наших интересах. Создайте манекен FrameworkElement в XAML с установленной видимостью для свертывания. FrameworkElement наследует DataContext от родительского контейнера, который может быть Window или UserControl.

И может использовать это в DataGrid:

    <FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test"
                                Binding="{Binding Name}"
                                Visibility="{Binding DataContext.IsEnable,
                                          Source={x:Reference dummyElement}}"/>
        </DataGrid.Columns>
    </DataGrid>

Ответ 2

 <Window.Resources>
        <ResourceDictionary>
            <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}" />
        </ResourceDictionary>
 </Window.Resources>

 <ContentControl Content="{StaticResource ProxyElement}" Visibility="Collapsed" />
     <mch:MCHDataGrid Height="350"
                         AutoGenerateColumns="False"
                         FlowDirection="LeftToRight"
                         ItemsSource="{Binding PayStructures}"
                         SelectedItem="{Binding SelectedItem}">
            <DataGrid.Columns>
                <DataGridTemplateColumn Width="70"
                                        Header="name"
                                        IsReadOnly="True"
                                        Visibility="{Binding DataContext.IsShowName,
                                                             Source={StaticResource ProxyElement}}">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding FieldName}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

            </DataGrid.Columns>
        </mch:MCHDataGrid>

в поле зрения

 private Visibility _isShowName;
        public Visibility IsShowName
        {
            get { return _isShowName; }
            set
            {
                _isShowName = value;
                OnPropertyChanged();
            }
        }