你的位置:首页 > ASP.net教程

[ASP.net教程]MVVM框架下 WPF隐藏DataGrid一列


最近的一个项目,需要在部分用户登录的时候,隐藏DataGrid中的一列,但是常规的绑定不好使,在下面举个例子。

XAML部分代码

<Window x:Class="DataGridColumn.MainWindow"    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    ="http://schemas.microsoft.com/winfx/2006/xaml"    ="clr-namespace:DataGridColumn"    Title="MainWindow" Height="350" Width="525">  <Grid>    <Grid.RowDefinitions>      <RowDefinition Height="50"/>      <RowDefinition Height="*"/>    </Grid.RowDefinitions>    <StackPanel Grid.Row="0">      <Button Content="显示" Command="{Binding Button1Command}"/>      <Button Content="隐藏" Command="{Binding Button2Command}"/>    </StackPanel>    <DataGrid Grid.Row="1" AutoGenerateColumns="False">      <DataGrid.Columns>        <DataGridTextColumn Header="列一"/>        <DataGridTextColumn Header="列二"/>        <DataGridTextColumn Header="列三" Visibility="{Binding DataContext.IsVisibility,RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>              </DataGrid.Columns>    </DataGrid>  </Grid></Window>

XAML

ViewModel部分代码

using GalaSoft.MvvmLight.Command;using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;namespace DataGridColumn{  public class MainWindowVM : INotifyPropertyChanged  {    public MainWindowVM()    {      IsVisibility = Visibility.Hidden;    }    public event PropertyChangedEventHandler PropertyChanged;    private void INotifyPropertyChanged(string name)    {      if (PropertyChanged != null)      {        PropertyChanged(this, new PropertyChangedEventArgs(name));      }    }    private Visibility isVisibility;    public Visibility IsVisibility    {      get { return isVisibility; }      set      {        isVisibility = value;        INotifyPropertyChanged("IsVisibility");      }    }    private RelayCommand button1Command;    public RelayCommand Button1Command    {      get      {        return button1Command = new RelayCommand(          () =>          {            IsVisibility = Visibility.Visible;          });      }    }    private RelayCommand button2Command;    public RelayCommand Button2Command    {      get      {        return button2Command = new RelayCommand(          () =>          {            IsVisibility = Visibility.Hidden;          });      }    }  }}

ViewModel

显示效果如下

本该隐藏的第三列,没有隐藏,比较困惑,然后百度了一下,在两个网站上得到了答案,网站一,网站二

出现问题的原因是,DataGridTextColumn不属于Visual Tree

解决方案有两种:

一、采用代理(网站一)

1、添加一个FrameworkElement的代理

<Window.Resources>    <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Window.Resources>

2、用一个不可见的ContentControl绑定上一步的FrameworkElement代理

<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"/>

3、用代理做为Visibility的数据源

<DataGridTextColumn Header="列二" Visibility="{Binding DataContext.IsVisibility,Source={StaticResource ProxyElement}}"/>

 

二、使用Freezable(网站二)

 根据MSDN里Freezable的相关文档,在Remarks下有这样的一句话

  • Detailed change notification: Unlike other DependencyObject objects, a Freezable object provides change notifications when sub-property values change.

大意就是和其他的DependencyObject相比,在子属性值更改时, Freezable 对象提供更改通知。个人认为应该是由于Freezable有这个特点,所以才能被用在这里。

代码如下

BindingProxy类

public class BindingProxy:Freezable  {    protected override Freezable CreateInstanceCore()    {      return new BindingProxy();      //throw new NotImplementedException();    }    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));    public object Data    {      get { return (object)GetValue(DataProperty); }      set { SetValue(DataProperty, value); }    }  }

BindingProxy

XAML引用BindingProxy

<local:BindingProxy x:Key="proxy" Data="{Binding}"/>

Visibility绑定

<DataGridTextColumn Header="列三" Visibility="{Binding Data.IsVisibility,Source={StaticResource proxy}}"/>        

效果如下,列二用的是方法一,列三用的是方法二

作为新手,只能理解如此,希望有大神可以给好好的讲解一下,谢谢。