在项目中使用DataGrid需要根据业务动态隐藏某些列,思路都是给DataGrid中列的Visibility属性绑定值来实现(项目使用MVVM),如下

  1. <DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},Path=DataContext.IsVisible,Converter={StaticResource BooleanToVisibilityConverter}}"></DataGridTextColumn>

如果不是在DataGridTextColumn上绑定,那么这段代码是可以工作的,问题出在DataGridTextColumn上,我们来看它的继承层次

它不是FrameworkElement的派生类,所以它不具有DataContext属性,也就是说,即使DataGrid有DataContext,DataGridTextColumn也不能得到它,Visibility找不到DataContext自然绑定不上,这就是为什么上面的绑定失效的原因,同样其他类型的列也有同样的问题。那么如何优雅地解决问题呢?国际友人给出了这样一个方法,既然DataGridTextColumn不能从父级那里得到DataContext,那么直接给她的Visibility指定一个DataContext,实现如下

  • 首先创建一个可以承载DataContext的绑定代理类BindingProxy
  • 然后将这个BindingProxy当作资源,获得DataContext
  • 将DataGridTextColumn的Visibility的DataContext指定为这个BindingProxy

BindingProxy.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6.  
  7. namespace WPF_DataContext_Sample
  8. {
  9. public class BindingProxy:Freezable
  10. {
  11. protected override Freezable CreateInstanceCore()
  12. {
  13. return new BindingProxy();
  14.  
  15. }
  16.  
  17. public object DataContext
  18. {
  19. get
  20. {
  21. return (object)GetValue(DataContextProperty);
  22. }
  23. set
  24. {
  25. SetValue(DataContextProperty, value);
  26. }
  27. }
  28.  
  29. // Using a DependencyProperty as the backing store for DataContext. This enables animation, styling, binding, etc...
  30. public static readonly DependencyProperty DataContextProperty =
  31. DependencyProperty.Register("DataContext", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
  32. }
  33. }

MainWindow.xaml

  1. <Window x:Class="WPF_DataContext_Sample.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:wpfDataContextSample="clr-namespace:WPF_DataContext_Sample"
  5. Title="MainWindow" Height="350" Width="525">
  6. <Window.Resources>
  7. <wpfDataContextSample:Converter x:Key="Converter"></wpfDataContextSample:Converter>
  8.  
  9. <wpfDataContextSample:BindingProxy x:Key="BindingProxy" DataContext="{Binding}"></wpfDataContextSample:BindingProxy>
  10. </Window.Resources>
  11. <Grid>
  12. <Grid.RowDefinitions>
  13. <RowDefinition/>
  14. <RowDefinition Height="0.1*"/>
  15. </Grid.RowDefinitions>
  16. <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Students}">
  17. <DataGrid.Columns>
  18.  
  19. <DataGridTextColumn Header="Id" Binding="{Binding Id}"></DataGridTextColumn>
  20.  
  21. <!--这样的绑定会失败-->
  22. <!--<DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},Path=DataContext.IsShow,Converter={StaticResource BooleanToVisibilityConverter}}"></DataGridTextColumn>-->
  23.  
  24. <DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding DataContext.IsShow,Source={StaticResource BindingProxy},Converter={StaticResource Converter}}"></DataGridTextColumn>
  25.  
  26. <DataGridTextColumn Header="Sex" Binding="{Binding Sex}"></DataGridTextColumn>
  27.  
  28. </DataGrid.Columns>
  29. </DataGrid>
  30.  
  31. <StackPanel Orientation="Horizontal" Grid.Row="1">
  32. <Button Width="100" Height="30" Content="隐藏Name" Click="ButtonBase_OnClick"></Button>
  33. </StackPanel>
  34. </Grid>
  35. </Window>

这样就能优雅地解决了这个问题

原文地址http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

Demo:WPF_DataContextAndDataGridTextColumn_Sample.rar

由DataGridTextColumn不能获取到父级DataContext引发的思考的更多相关文章

  1. Java IO,io,文件操作,删除文件,删除文件夹,获取文件父级目录

    Java IO,io,文件操作,删除文件,删除文件夹,获取文件父级目录 这里先简单的贴下常用的方法: File.separator //当前系统文件分隔符 File.pathSeparator // ...

  2. jQuery获取所有父级元素及同级元素及子元素的方法

    jQuery获取所有父级元素及同级元素及子元素的方法 1.获取父级元素 $("#id").parent() 获取其父级元素 $("#id").parents() ...

  3. mysql获取子父级节点

    获取所有子节点 DROP FUNCTION IF EXISTS `F_Co29_GetAllChildrenIdsOfTaskevent`;DELIMITER //CREATE FUNCTION `F ...

  4. SQL根据指定节点ID获取所有父级节点和子级节点

    --根据指定节点ID获取所有子节点-- WITH TEMP AS ( SELECT * FROM table_name WHERE Id=' --表的主键ID UNION ALL SELECT T0. ...

  5. SQL根据指定节点ID获取所有父级节点和子级节点(转载)

    --根据指定节点ID获取所有子节点-- WITH TEMP AS ( ' --表的主键ID UNION ALL SELECT T0.* FROM TEMP,table_name T0 WHERE TE ...

  6. el-tree点击获取直接父级的属性

    这里是可以一直往上获取它的直接父级的所有属性以及状态 通过这两个事件其中的一个 在方法里可以写上 methods:{ curCheck(data,state){ const curNode = thi ...

  7. mysql oracle sql获取树 父级 子级 及自己

    select * from ( select t.*,d.TABLE_NAME,d.QUERY_SQL,d.data_control_col,d.id table_id,d.where_sql fro ...

  8. jQuery使用(四):DOM操作之查找兄弟元素和父级元素

    查找兄弟元素 向下查找兄弟元素 next() nextAll() nextUntil() 向上查找兄弟元素 prev() prevAll() prevUntil() 查找所有兄弟元素 siblings ...

  9. js动态绑定class(当前父级div下的子元素有没有这个class,有的话移除,没有的话添加)

    <div class="layui-inline" id=‘’   onclick="changeType(id)">                ...

随机推荐

  1. puppet学习笔记(二)

    在puppet安装完成之后我们就可以动手开始第一个puppet实验了,此实验就以批量推送文件为例吧. 1.获取module路径 这里的module就是指一个模块,可以把puppet想象成一个个项目的部 ...

  2. 18 多线程编程 - 《Python 核心编程》

  3. 边工作边刷题:70天一遍leetcode: day 83

    Find the Duplicate Number 要点:通过Pigeonhole principle对值空间做binary search,具体来说, low,mid,high都是值空间,所以范围是[ ...

  4. HDU 4964 Emmet --模拟

    题意:给你一个字符串,要求把它按语法转化成HTML格式. 分析:这题其实不难,就是一个递归的事情,当时忽略了括号嵌套的情况,所以一直WA,后来加上这种情况后就过了.简直醉了. 处理id和class时, ...

  5. 二分匹配之最大权值匹配算法---KM模板

    百科:http://baike.baidu.com/link?url=vbM3H4XmfrsWfP-epdlR2sVKSNzOq4hXnWDqm5uo8fd7VWsF2SmhDV35XyVUDvVjv ...

  6. Unity 跑酷Demo难题总结

    问题1:路面拼接处理 在拼接路的时候,如果两个路挨的太近就会出现贴图闪烁,如下所示 解决办法 如果把路改小就会出现断层,但不会出现贴图闪烁 PS:我是把贴图放在Cube上的,所以路是有厚度. 附注 刚 ...

  7. MongoDB学习(四)客户端工具备份数据库

    在上一篇MongoDB学习(三)中讲解了如何在服务器端进行数据的导入导出与备份恢复,本篇介绍下如何利用客户端工具来进行远程服务器的数据备份到本地. 以客户端工具MongoVUE为例来进行讲解: 1.首 ...

  8. java9-4 包

    面试题: package,import,class有没有顺序关系? 有. package > import > class Package:只能有一个 import:可以有多个 class ...

  9. C语言 百炼成钢10

    //题目28:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁.问第4个人岁数,他说比第 //3个人大2岁.问第三个人,又说比第2人大两岁.问第2个人,说比第一个人大两岁.最后 //问第一个人 ...

  10. CENTOS7 添加自定义快捷键(启动TERMINAL,显示桌面等)

    centos7中不自带启动终端的快捷键,可以自定义添加. 点击右上角的用户名,点击设置,在设置面板点击键盘,选择快捷键选项卡进入快捷键设置界面. 点击“+”添加快捷键.名称自定义(如"启动终 ...