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

<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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows; namespace WPF_DataContext_Sample
{
public class BindingProxy:Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy(); } public object DataContext
{
get
{
return (object)GetValue(DataContextProperty);
}
set
{
SetValue(DataContextProperty, value);
}
} // Using a DependencyProperty as the backing store for DataContext. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataContextProperty =
DependencyProperty.Register("DataContext", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
}
}

MainWindow.xaml

<Window x:Class="WPF_DataContext_Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfDataContextSample="clr-namespace:WPF_DataContext_Sample"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<wpfDataContextSample:Converter x:Key="Converter"></wpfDataContextSample:Converter> <wpfDataContextSample:BindingProxy x:Key="BindingProxy" DataContext="{Binding}"></wpfDataContextSample:BindingProxy>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0.1*"/>
</Grid.RowDefinitions>
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Students}">
<DataGrid.Columns> <DataGridTextColumn Header="Id" Binding="{Binding Id}"></DataGridTextColumn> <!--这样的绑定会失败-->
<!--<DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},Path=DataContext.IsShow,Converter={StaticResource BooleanToVisibilityConverter}}"></DataGridTextColumn>--> <DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding DataContext.IsShow,Source={StaticResource BindingProxy},Converter={StaticResource Converter}}"></DataGridTextColumn> <DataGridTextColumn Header="Sex" Binding="{Binding Sex}"></DataGridTextColumn> </DataGrid.Columns>
</DataGrid> <StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Width="100" Height="30" Content="隐藏Name" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Grid>
</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. 使用O_APPEND标志打开文件对文件进行lseek后进行读写的问题

    fd = open("./newfile", O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); ) { perror("open&qu ...

  2. sqoop sample code

    本文使用的数据库是mysql的sample database employees. download url:https://launchpad.net/test-db/employees-db-1/ ...

  3. Hbase step by step 完全分布式安装

    Step1: download and extract the packages: http://mirror.bit.edu.cn/apache/hbase/stable/ Step2: set t ...

  4. POJ 1984 Navigation Nightmare

    并查集,给n个点和m条边,每条边有方向和长度,再给q个询问,第i个询问查询两个点之间在Ti时刻时的曼哈顿距离(能连通则输出曼哈顿距离,否则输出-1) 这题跟Corporative Network 有点 ...

  5. JMeter学习(三)元件的作用域与执行顺序

    1.元件的作用域 JMeter中共有8类可被执行的元件(测试计划与线程组不属于元件),这些元件中,取样器是典型的不与其它元件发生交互作用的元件,逻辑控制器只对其子节点的取样器有效,而其它元件(conf ...

  6. 最常用的DOS命令

    ping:利用它可以检查网络是否能够连通,用好它可以很好地帮助我们分析判定网络故障,如ping 127.0.0.1tracert:跟踪路由,查询到相应网站的服务器之间所需经过的路由器个数,如trace ...

  7. 15Spring_AOP编程(AspectJ)_抛出通知

  8. DWM 窗体玻璃效果实现

    我一直盼望着 Windows 新版本的发布.令人感兴趣的事情莫过于浏览 MSDN® 和 SDK 文档,查找一些可以利用和依赖的最新创新,然后让朋友和同事以及您的老板(如果幸运的话)大开眼界.Windo ...

  9. Contains Duplicate II

    Given an array of integers and an integer k, find out whether there there are two distinct indices i ...

  10. Linux 进程与线程二(等待--分离--取消线程)

    int pthread_join(pthread_t thr,void **thr_return); pthread_join函数用于挂起当前线程,直至th指定的线程终止为止. 如果另一个线程返回值不 ...