2012-01-13 73 views
13

我想列知名度綁定到這樣的其他元素:DataGridTextColumn能見度綁定

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
</Window.Resources> 
<StackPanel> 
    <CheckBox x:Name="chkColumnVisible" Content="Show column" /> 
    <DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="Column1" Visibility="{Binding ElementName=chkColumnVisible, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"/> 
     </DataGrid.Columns> 
    </DataGrid> 
</StackPanel> 

,但我得到這個錯誤在VS輸出:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsChecked; DataItem=null; target element is 'DataGridTextColumn' (HashCode=48860040); target property is 'Visibility' (type 'Visibility') 

是有一種純粹的XAML方式來實現這一點?

回答

35

DataGrid的列是沒有出現在視覺或邏輯樹中的抽象對象。您不能使用ElementNameRelativeSourceSource結合x:Reference應的工作,雖然:

Visibility="{Binding Source={x:Reference chkColumnVisible}, 
        Path=IsChecked, 
        Converter={StaticResource BooleanToVisibilityConverter}}" 
+0

+1鏈接至x:參考! – 2012-01-13 08:37:26

+0

謝謝,它的工作原理!但是爲了讓我可以睡覺:)......我完全可以理解爲什麼RelativeSource不起作用,因爲它與目標相關。但究竟是ElementName的問題?我以爲我通過使用ElementName給出了一個絕對源代碼的綁定(顯然,我錯了!),所以如果目標是在視覺或邏輯樹上或不是,那麼無關緊要。 – 2012-01-13 08:38:40

+0

@ErenErsonmez:'ElementName'使用當前的名稱範圍來解析名稱,而據我所知,名稱範圍依賴於樹。 – 2012-01-13 09:37:25

10

我寫了的MarkupExtension吧:

using System; 
using System.ComponentModel; 
using System.Linq; 
using System.Reflection; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Markup; 
using System.Xaml; 

/// <summary> 
/// Binds to the datacontext of the current root object or ElementName 
/// </summary> 
[MarkupExtensionReturnType(typeof(object))] 
public class NinjaBinding : MarkupExtension 
{ 
    private static readonly DependencyObject DependencyObject = new DependencyObject(); 
    private static readonly string[] DoNotCopy = { "Path", "Source", "ElementName", "RelativeSource", "ValidationRules" }; 
    private static readonly PropertyInfo[] CopyProperties = typeof(Binding).GetProperties().Where(x => !DoNotCopy.Contains(x.Name)).ToArray(); 
    public NinjaBinding() 
    { 
    } 

    public NinjaBinding(Binding binding) 
    { 
     Binding = binding; 
    } 

    public Binding Binding { get; set; } 

    private bool IsInDesignMode 
    { 
     get { return DesignerProperties.GetIsInDesignMode(DependencyObject); } 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (Binding == null) 
     { 
      throw new ArgumentException("Binding == null"); 
     } 
     if (IsInDesignMode) 
     { 
      return DefaultValue(serviceProvider); 
     } 
     Binding binding = null; 
     if (Binding.ElementName != null) 
     { 
      var reference = new Reference(Binding.ElementName); 
      var source = reference.ProvideValue(serviceProvider); 
      if (source == null) 
      { 
       throw new ArgumentException("Could not resolve element"); 
      } 
      binding = CreateElementNameBinding(Binding, source); 
     } 
     else if (Binding.RelativeSource !=null) 
     { 
      throw new ArgumentException("RelativeSource not supported"); 
     } 
     else 
     { 
      var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider)); 
      if (rootObjectProvider == null) 
      { 
       throw new ArgumentException("rootObjectProvider == null"); 
      } 
      binding = CreateDataContextBinding((FrameworkElement) rootObjectProvider.RootObject, Binding); 
     } 

     var provideValue = binding.ProvideValue(serviceProvider); 
     return provideValue; 
    } 

    private static Binding CreateElementNameBinding(Binding original, object source) 
    { 
     var binding = new Binding() 
     { 
      Path = original.Path, 
      Source = source, 
     }; 
     SyncProperties(original, binding); 
     return binding; 
    } 

    private static Binding CreateDataContextBinding(FrameworkElement rootObject, Binding original) 
    { 
     string path = string.Format("{0}.{1}", FrameworkElement.DataContextProperty.Name, original.Path.Path); 
     var binding = new Binding(path) 
     { 
      Source = rootObject, 
     }; 
     SyncProperties(original, binding); 
     return binding; 
    } 

    private static void SyncProperties(Binding source, Binding target) 
    { 
     foreach (var copyProperty in CopyProperties) 
     { 
      var value = copyProperty.GetValue(source); 
      copyProperty.SetValue(target, value); 
     } 
     foreach (var rule in source.ValidationRules) 
     { 
      target.ValidationRules.Add(rule); 
     } 
    } 

    private static object DefaultValue(IServiceProvider serviceProvider) 
    { 
     var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); 
     if (provideValueTarget == null) 
     { 
      throw new ArgumentException("provideValueTarget == null"); 
     } 
     var dependencyProperty = (DependencyProperty)provideValueTarget.TargetProperty; 
     return dependencyProperty.DefaultMetadata.DefaultValue; 
    } 
} 

它能夠結合當前根客體的DataContext的{窗口,用戶控件,... }

示例用法(可見&可視性是在視圖模型的屬性):

<DataGrid> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="DataContext" Visibility="{dataGridBox:NinjaBinding Binding={Binding Visibility}}" /> 
     <DataGridTextColumn Header="Converter" Visibility="{dataGridBox:NinjaBinding Binding={Binding Visible, Converter={StaticResource BooleanToVisibilityConverter}}}" /> 
     <DataGridTextColumn Header="ElementName" Visibility="{dataGridBox:NinjaBinding Binding={Binding IsChecked, ElementName=CheckBox, Converter={StaticResource BooleanToVisibilityConverter}}}" /> 
    </DataGrid.Columns> 
</DataGrid> 
+0

由於某種原因,我不適用於...'BindingExpression路徑錯誤:'對象'''NameFixupToken'(HashCode = 55620207)'找不到'ValidationColumnVisibility'屬性。 BindingExpression:路徑= ValidationColumnVisibility; DataItem ='NameFixupToken'(HashCode = 55620207);目標元素是'DataGridTextColumn'(HashCode = 62066456);目標屬性是'可見性'(類型'可見性')' – Bartosz 2016-02-01 16:24:09