绑定WPF中DataGridColumn的可见性

ygo*_*goe 63 wpf xaml datagrid visibility

如何DataGrid通过绑定隐藏WPF中的列?

这就是我做的:

<DataGridTextColumn Header="Column header"
                    Binding="{Binding ColumnValue}"
                    Width="100"
                    ElementStyle="{StaticResource DataGridRightAlign}"
                    Visibility="{Binding MyColumnVisibility}" />
Run Code Online (Sandbox Code Playgroud)

这就是我得到的(除了列仍然可见):

System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement.BindingExpression:路径= MyColumnVisibility; 的DataItem = NULL; target元素是'DataGridTextColumn'(HashCode = 1460142); 目标属性是"可见性"(类型"可见性")

不知道什么是治理手段.在我窗口的某个地方是否有一些总统先生决定哪些有效,哪些无效?或者我必须投票?

在网上搜索解决方案时,我发现有十几页具有很好的标题,但完全不相关或不可复制的内容.所以这似乎是关于这个问题的第一个问题.任何的想法?

Roh*_*ats 146

首先DataGridTextColumn或任何其他受支持的dataGrid列不在Visual树中DataGrid.因此,在默认情况下它不会继承DataContextDataGrid.但是,它Binding仅适用于DP,而不适用于DataGridColumn上的其他DP.

因为,它们不在同一个VisualTree中,因此任何尝试使用DataContext RelativeSource都不会起作用,因为DataGrid将无法遍历到DataGrid.

有两种方法可以实现这一点:


首先使用Freezable类 - Freezable对象可以继承DataContext,即使它们不在可视树或逻辑树中.所以,我们可以利用它来使用它.

首先创建继承自FreezableDataDP的类,我们可以使用它在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));
}
Run Code Online (Sandbox Code Playgroud)

现在,在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>
Run Code Online (Sandbox Code Playgroud)

其次,您可以使用ElementName或引用XAML中的任何UI元素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>
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这第二种方法.它很容易编写,我已经有另一个相同的可见性控件,所以我可以给它一个`x:Name`并引用它的`Visibility`属性.不是那么直截了当,沿途更多地转向侧面,但仍然很简单.我想,当绑定到引用元素的DataContext属性时,你"劫持"另一个元素以与其他无法访问的DataGridColumn共享其DataContext,对吧?dummyElement就是桥梁. (2认同)
  • @LonelyPixel - 是的,你做对了.我尝试从其DataGrid兄弟孩子劫持DataContext,因为他们都共享相同的DataContext,除非明确设置.我本可以使用x:引用DataGrid本身,但这会导致循环依赖. (2认同)
  • 就个人而言,如果你问我,我喜欢第一种方法。开销只是创建一个类,但是一旦你在你的小猫中拥有它,在 XAML 中编写代码就变得容易多了。我确实更经常使用它。 (2认同)
  • @JMIII不知道,我现在不在任何地方使用它。另外,只要最终运行XAML编辑器,我也不关心XAML编辑器了解什么(不是很多)。 (2认同)

Mey*_*ini 15

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

<!-- Necessary for binding to resolve: adds reference to ProxyElement to tree.-->
<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>
Run Code Online (Sandbox Code Playgroud)

视图模型中绑定属性的示例:

private Visibility _isShowName;

public Visibility IsShowName
{
    get { return _isShowName; }
    set
    {
        _isShowName = value;
        OnPropertyChanged();
    }
}
Run Code Online (Sandbox Code Playgroud)