DataGridTextColumn可见性绑定

我正在尝试将列可见性绑定到另一个元素的可见性,如下所示:

            

但我在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方法来实现这一目标?

DataGrid的列是未出现在可视树或逻辑树中的抽象对象。 您不能使用ElementNameRelativeSourceSourcex:Reference结合x:Reference应该工作:

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

我为它写了一个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; ///  /// Binds to the datacontext of the current root object or ElementName ///  [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 {Window,UserControl,…}

示例用法(Visible&Visibility是viewmodel中的属性):

        

Johan Larsson的解决方案工作得很好,只有来自Binding的FallbackValue没有转发,所以我改变了它:

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

所以它可以像这样使用,例如绑定到标题: