[No0000123]WPF DataGrid Columns Visibility的绑定

场景:根据配置文件显示DataGrid中的某些列。

  问题:Columns集合只是DataGrid的一个属性,这个集合在逻辑树或视觉树中是看不到的,也不会继承DataContext属性。

方法一:对DataGridColumn附加DataContext属性

  该方法需要用到一个帮助类(需要创建一个全局实例),具体内容如下:

public class DataGridContextHelper
    {
        static DataGridContextHelper()
        {

            DependencyProperty dp = FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));
            FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid),
            new FrameworkPropertyMetadata
               (null, FrameworkPropertyMetadataOptions.Inherits,
               new PropertyChangedCallback(OnDataContextChanged)));

        }

        public static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGrid grid = d as DataGrid;
            if (grid != null)
            {
                foreach (DataGridColumn col in grid.Columns)
                {
                    col.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
                }
            }
        }
    }

前台绑定示例

<DataGridTextColumn x:Name="col2" Header="TestColumn"
Visibility="{Binding (FrameworkElement.DataContext).Show,
RelativeSource={RelativeSource Self},
Converter={StaticResource cc}}
"></DataGridTextColumn>

后台绑定示例

var binding = new Binding();
    binding.Mode = BindingMode.OneWay;
    binding.RelativeSource=new RelativeSource(RelativeSourceMode.Self);
    binding.Converter = new BooleanToVisibilityConverter();
    binding.Path=new PropertyPath("(FrameworkElement.DataContext).Show");
    BindingOperations.SetBinding(obj, DataGridColumn.VisibilityProperty, binding);

方法二:通过Source直接与Vm绑定

  示例代码:

var binding = new Binding();
    binding.Mode = BindingMode.OneWay;
    binding.Source = vm;
    binding.Converter = new BooleanToVisibilityConverter();
    binding.Path = new PropertyPath("Show");
    BindingOperations.SetBinding(obj, DataGridColumn.VisibilityProperty, binding);

方法三:通过Source与VM的一个代理类进行绑定

  代理类

  Freezable可以继承DataContext即使它们不在视觉树或逻辑树中

public class BindingProxy : Freezable
    {
        #region Overrides of Freezable

        protected override Freezable CreateInstanceCore()
        {
            return new BindingProxy();
        }

        #endregion

        public object Data
        {
            get { return (object)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(object),
                                         typeof(BindingProxy));
    }

前台绑定代码

<DataGrid x:Name="dg" HorizontalAlignment="Left" VerticalAlignment="Top" Height="253" Width="436" ItemsSource="{Binding Persons}"
 AutoGenerateColumns="False">
  <DataGrid.Resources>
      <dgTest:BindingProxy x:Key="proxy" Data="{Binding}"/>
  </DataGrid.Resources>
    <DataGrid.Columns>
       <DataGridTextColumn x:Name="col1" Header="TestColumn" Binding="{Binding Name}"></DataGridTextColumn>
        <DataGridTextColumn x:Name="col2" Header="TestColumn"
         Visibility="{Binding (FrameworkElement.DataContext).Show,
RelativeSource={RelativeSource Self},
Converter={StaticResource cc}}
"></DataGridTextColumn> <DataGridTextColumn x:Name="col3" Header="TestColumn" Visibility="{Binding Data.Show,Source={StaticResource proxy},
Converter={StaticResource cc}}
"></DataGridTextColumn> </DataGrid.Columns> </DataGrid>

方法四:通过一个代理控件来实现

  代理控件与代理对象的解决方式类似,都是因为其可以继承DataContext属性,只是一个在逻辑树中看的到,一个看不到。示例如下:

<FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test"
              Binding="{Binding Name}"
              Visibility="{Binding DataContext.IsEnable,
              Source={x:Reference dummyElement}}"/>
        </DataGrid.Columns>
    </DataGrid>

 

posted @ 2018-04-09 14:41  CharyGao  阅读(1031)  评论(0编辑  收藏  举报