由DataGridTextColumn不能获取到父级DataContext引发的思考

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

由DataGridTextColumn不能获取到父级DataContext引发的思考
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},Path=DataContext.IsVisible,Converter={StaticResource BooleanToVisibilityConverter}}"></DataGridTextColumn>
由DataGridTextColumn不能获取到父级DataContext引发的思考


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

由DataGridTextColumn不能获取到父级DataContext引发的思考

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

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

BindingProxy.cs

由DataGridTextColumn不能获取到父级DataContext引发的思考
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));
    }
}
由DataGridTextColumn不能获取到父级DataContext引发的思考

MainWindow.xaml

由DataGridTextColumn不能获取到父级DataContext引发的思考
<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>
由DataGridTextColumn不能获取到父级DataContext引发的思考

 

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

原文地址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引发的思考

上一篇:iOS显示PDF


下一篇:UVa OJ 10300