绑定数据网格列可见性MVVM

发布于 2024-12-09 01:18:28 字数 2608 浏览 0 评论 0 原文

.Net 3.5

我知道列不会继承数据上下文,通过阅读其他帖子,我认为这会起作用:

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>

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

.Net 3.5

I know that the columns doesn't inherit the datacontext and by reading other posts i thought this would work:

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

However of course it doesn't..
The output window does not complain, it seems that the resource i found but the viewmodel property is newer called.

This is the entire 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>

I have read pretty much every single solution to this problem and nothing works..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寄与心 2024-12-16 01:18:28

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

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

  1. 在祖先面板的Resources中添加代理FrameworkElement

  2. 将其托管到与其Content绑定的不可见ContentControl中。

  3. 将此 ProxyElement 用作可见性绑定中数据上下文源的 StaticResource

     ;
         
            <本地:BooleanToVisibilityConverter
                   x:Key="BooleanToVisibilityConverter" />
    
            
         
         
         
             
                 
             
         
      
    

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

Silverlight 用户

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

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

     ;
         
    
  2. 编写附加属性以针对内容控件保存文本块。

     
    
  3. 在附加的依赖属性更改事件处理程序中,将内容控件的数据上下文绑定到文本块。

     private static void OnProxyElementPropertyChanged(
          DependencyObject depObj、DependencyPropertyChangedEventArgs e)
      {
            if (depObj 是 ContentControl && e.NewValue 是 TextBlock)
            {
                var 绑定 = new Binding("DataContext");
                绑定.Source = depObj;
                绑定.Mode = OneWay;
                BindingOperations.SetBinding(
                    (TextBlock)e.NewValue、TextBlock.DataContextProperty、绑定);
            }
      }
    

因此,通过这种方式,文本块可能不会连接到可视化树,但可能会意识到数据上下文的更改。

DataGridColumns are not part of visual tree so they are not connected to the data context of the DataGrid.

For them to connect together use proxy element approach like this...

  1. Add a proxy FrameworkElement in your ancestor panel's Resources.

  2. Host it into an invisible ContentControl bound to its Content.

  3. Use this ProxyElement as StaticResource for data context source in your visibility binding.

     <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> 
    

Apart from DataGridColumn, the above approach also works great to connect DataContext to Popups and ContextMenus (i.e. any element that is not connected to the visual tree).

Silverlight Users

Sadly setting contents of content controls with any framework elements is not allowed in silverlight. So the workaround would be (this is just a guidance code for silverlight) ...

  1. Change the framework element resource to something lightweight like a Textblock. (Silverlight does not allow specifying static resource of FrameworkElement type.)

     <StackPanel.Resources>
         <TextBlock x:Key="MyTextBlock" />
    
  2. Write an attached property to hold text block against the content control.

     <ContentControl Visibility="Collapsed" 
                     local:MyAttachedBehavior.ProxyElement="{StaticResource MyTextBlock}" />
    
  3. In the attached dependency property changed event handler, set the bind the data context of the content control to the text block's.

      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);
            }
      }
    

So this way the textblock may not be connected to the visual tree but will probably be aware of the data context changes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文