MVVM框架下 WPF隱藏DataGrid一列


最近的一個項目,需要在部分用戶登錄的時候,隱藏DataGrid中的一列,但是常規的綁定不好使,在下面舉個例子。

XAML部分代碼

<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>
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}}"/>                

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

作為新手,只能理解如此,希望有大神可以給好好的講解一下,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM