Связывание видимости 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 являются абстрактными объектами, которые не отображаются в визуальном или логическом дереве. Вы не можете использовать ElementName и RelativeSource . Source в сочетании с x:Reference должна работать, хотя:

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

Я написал для него разметку:

 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 работает отлично, только FallbackValue от Binding не перенаправляется, поэтому я изменил его следующим образом:

 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; } 

Поэтому его можно использовать так, например, для привязки к заголовку:

  
  • Как применить правило пользовательской сортировки к WPF DataGrid?
  • Как прокручивать в нижней части ScrollViewer автоматически с помощью Xaml и привязки?
  • Как создать вкладки трапеции в элементе управления вкладками WPF
  • Как реализовать навигационную кнопку в общих ресурсах приложений?
  • Редактирование одного клика в WPF DataGrid
  • имя не существует в пространстве имен clr-namespace
  • Связывание в текстовом столбце таблицы данных WPF
  • Стили сплава XAML
  • WPF, «Ссылка на объект не установлена ​​в экземпляр объекта» в Designer
  • Привязка видимости кнопки к значению bool в ViewModel
  • Доступ к ScrollViewer из ListBox из C #
  • Давайте будем гением компьютера.