最近的一個項目,須要在部分用戶登陸的時候,隱藏DataGrid中的一列,可是常規的綁定很差使,在下面舉個例子。html
XAML部分代碼windows
<Window x:Class="DataGridColumn.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="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>
ViewModel部分代碼app
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; }); } } } }
顯示效果以下mvvm
本該隱藏的第三列,沒有隱藏,比較困惑,而後百度了一下,在兩個網站上獲得了答案,網站一,網站二ide
出現問題的緣由是,DataGridTextColumn不屬於Visual Tree網站
解決方案有兩種:ui
1、採用代理(網站一)this
一、添加一個FrameworkElement的代理spa
<Window.Resources> <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Window.Resources>
二、用一個不可見的ContentControl綁定上一步的FrameworkElement代理代理
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"/>
三、用代理作爲Visibility的數據源
<DataGridTextColumn Header="列二" Visibility="{Binding DataContext.IsVisibility,Source={StaticResource ProxyElement}}"/>
2、使用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); } } }
XAML引用BindingProxy
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
Visibility綁定
<DataGridTextColumn Header="列三" Visibility="{Binding Data.IsVisibility,Source={StaticResource proxy}}"/>
效果以下,列二用的是方法一,列三用的是方法二
做爲新手,只能理解如此,但願有大神能夠給好好的講解一下,謝謝。