zoukankan      html  css  js  c++  java
  • 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}}"/>                

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

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

  • 相关阅读:
    xmind 8 readme
    【08】英语词汇速记大全1词根词缀记忆法
    【20180312】2018年03月12日(随想)
    大佬说
    github私有库购买信息
    【01】用构造器创建函数中的小知识
    【01】魔芋使用MDN的一点点经验
    10.12 telnet:远程登录主机
    10.11 arping:发送arp请求
    10.10 traceroute:追踪数据传输路由状况
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/4682736.html
Copyright © 2011-2022 走看看