绑定datagrid列可见性MVVM

jrb*_*jrb 49 c# wpf xaml wpftoolkit .net-3.5

.Net 3.5

我知道列不继承datacontext并通过阅读其他帖子我认为这将工作:

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

但是当然它没有..输出窗口没有抱怨,似乎我找到的资源但是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>
Run Code Online (Sandbox Code Playgroud)

我几乎已经阅读了这个问题的每一个解决方案,没有任何作用..

WPF*_*-it 102

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>
    </StackPanel> 
    
    Run Code Online (Sandbox Code Playgroud)

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

Silverlight用户

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

  1. 将框架元素资源更改为轻量级的东西Textblock.(Silverlight不允许指定FrameworkElement类型的静态资源.)

    <StackPanel.Resources>
        <TextBlock x:Key="MyTextBlock" />
    
    Run Code Online (Sandbox Code Playgroud)
  2. 编写附加属性以保留对内容控件的文本块.

    <ContentControl Visibility="Collapsed" 
                    local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" />
    
    Run Code Online (Sandbox Code Playgroud)
  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);
           }
     }
    
    Run Code Online (Sandbox Code Playgroud)

因此,文本块可能无法连接到可视树,但可能会知道数据上下文更改.

希望这可以帮助.

  • @ WPF-如果我们使用`ProxyElement`,你可以解释为什么需要`ContentControl`?[This](http://stackoverflow.com/questions/22073740/binding-visibility-for-datagridcolumn-in-wpf)解决方案使用类似的方法,但不需要`ContentControl`. (3认同)
  • @monstr,Freezable类破解了`DataContext` ...在我们的情况下'proxyelement'不是Freezable,所以如果它是在`VisualTree`中托管的话,它可以获得`DataContext`的唯一方法,如果它是一个可能的话`ContentControl`的`Content`.对于链接中的第二个解决方案,`NameScoping`在`Template`中不像`DataGridColumnHeaderTemplate`那样解析,因此`ElementName`不起作用.我提供的解决方案可以解决这两种情况. (3认同)