一尘不染

绑定datagrid列可见性MVVM

c#

.Net 3.5

我知道这些列不会继承datacontext,通过阅读其他文章,我认为这是可行的:

Visibility="{Binding RelativeSource={x:Static RelativeSource.Self},
                     Path=(FrameworkElement.DataContext).IsColumnNameVisible,
                     Converter={StaticResource boolToVisConverter}}"

但是,当然它不会。输出窗口没有抱怨,似乎我找到了资源,但是viewmodel属性是更新的。

这是整个DG:

<tk:DataGrid                                        
            VirtualizingStackPanel.IsVirtualizing="False"                                        
            Grid.Column="0"
            AlternationCount="2"
            AreRowDetailsFrozen="True"
            AutoGenerateColumns="False"
            Background="Transparent"
            BorderThickness="0"
            CanUserAddRows="False"
            CanUserReorderColumns="True"
            CanUserResizeRows="False"
            GridLinesVisibility="None"
            ItemsSource="{Binding Employees}"
            SelectionMode="Single"
            ColumnHeaderStyle="{StaticResource columnHeaderStyle}"
            RowHeaderStyle="{StaticResource rowHeaderStyle}"
            CellStyle="{StaticResource cellStyle}"
            RowStyle="{StaticResource rowStyle}" 
            ContextMenu="{StaticResource columnHeaderContextMenu}">
    <tk:DataGrid.Resources>
        <ContextMenu x:Key="columnHeaderContextMenu" ItemsSource="{Binding ColumnHeaderContextMenuItems}" />
        <Style TargetType="{x:Type ScrollBar}">
            <Setter Property="Background" Value="Transparent"/>
        </Style>                                    
        <Style TargetType="{x:Type tk:DataGridColumnHeader}">
            <Setter Property="Background" Value="Transparent"/>
        </Style>
    </tk:DataGrid.Resources>
    <tk:DataGrid.Triggers>
        <EventTrigger RoutedEvent="tk:DataGridRow.MouseDoubleClick">
            <EventTrigger.Actions>
                <BeginStoryboard Storyboard="{StaticResource showDetailGrid}"/>
            </EventTrigger.Actions>
        </EventTrigger>
    </tk:DataGrid.Triggers>
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn IsReadOnly="True" Header="test" Binding="{Binding Name, Mode=OneWay}" Visibility="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(FrameworkElement.DataContext).IsColumnNameVisible, Converter={StaticResource boolToVisConverter}}"  />
    </tk:DataGrid.Columns>
</tk:DataGrid>

我已经阅读了几乎所有解决此问题的方法,但是没有任何效果。


阅读 246

收藏
2020-05-19

共1个答案

一尘不染

DataGridColumns不是可视化树的一部分,因此它们未连接到的数据上下文DataGrid

为了让他们 连接 在一起,使用像这样的代理元素方法…

  1. FrameworkElement在祖先面板的中添加代理Resources
  2. ContentControl将其托管到与其无形的绑定中Content
  3. 将其ProxyElement用作StaticResource可见性绑定中的数据上下文源。
    <StackPanel>
    <StackPanel.Resources>
       <local:BooleanToVisibilityConverter
              x:Key="BooleanToVisibilityConverter" />
    
       <FrameworkElement x:Key="ProxyElement"
                         DataContext="{Binding}"/>
    </StackPanel.Resources>
    <ContentControl Visibility="Collapsed"
                Content="{StaticResource ProxyElement}"/>
    <DataGrid AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn
                   Visibility="{Binding DataContext.IsTextColumnVisibile,
                                        Source={StaticResource ProxyElement},
                                        Converter={StaticResource
                                            BooleanToVisibilityConverter}}"
                   Binding="{Binding Text}"/>
        </DataGrid.Columns>
    </DataGrid>
    

除之外DataGridColumn,上述方法还可以很好地连接DataContextPopups和ContextMenus(即未连接到可视树的任何元素)。

Silverlight用户

遗憾的是,silverlight不允许使用任何框架元素设置内容控件的内容。因此,解决方法是(这只是Silverlight的指导代码)…

  1. 将框架元素资源更改为轻量级的内容,例如Textblock。(Silverlight不允许指定FrameworkElement类型的静态资源。)

    <StackPanel.Resources>
    <TextBlock x:Key="MyTextBlock" />
    
  2. 编写一个附加属性以针对内容控件保留文本块。

    <ContentControl Visibility="Collapsed" 
                local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" />
    
  3. 在附加的依赖项属性已更改的事件处理程序中,将内容控件的数据上下文设置为绑定到文本块的上下文。

     private static void OnProxyElementPropertyChanged(
     DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    

    {
    if (depObj is ContentControl && e.NewValue is TextBlock)
    {
    var binding = new Binding(“DataContext”);
    binding.Source = depObj;
    binding.Mode = OneWay;
    BindingOperations.SetBinding(
    (TextBlock)e.NewValue, TextBlock.DataContextProperty, binding);
    }
    }

因此,此文本块可能不会连接到可视树,但 可能 会意识到数据上下文的变化。

希望这可以帮助。

2020-05-19