標籤:
情境:根據設定檔顯示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>
WPF DataGrid Visibility的綁定