2012-01-13 13 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> 

लेकिन मैं वी.एस. उत्पादन में इस त्रुटि मिलती है:

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') 

है इसे पूरा करने के लिए एक शुद्ध एक्सएएमएल तरीका है?

उत्तर

35

DataGrid के कॉलम दृश्य वस्तुएं या तार्किक पेड़ में प्रकट नहीं होने वाली सार वस्तुएं हैं। आप ElementName और RelativeSource का उपयोग नहीं कर सकते। x:Reference के साथ संयोजन में Source हालांकि काम करना चाहिए:

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

+1 x के लिए लिंक के लिए +1: संदर्भ! –

+0

धन्यवाद, यह काम करता है! लेकिन इसलिए कि मैं सो सकता हूं:) ... मैं निश्चित रूप से समझ सकता हूं कि सापेक्ष स्रोत काम क्यों नहीं करेगा, क्योंकि यह लक्ष्य के सापेक्ष है। लेकिन ElementName के साथ समस्या क्या है ?? मैंने सोचा कि मैं एलिमेंटनाम का उपयोग कर एक पूर्ण स्रोत को बाध्यकारी दे रहा था (और जाहिर है कि मैं गलत हूं!) इससे कोई फर्क नहीं पड़ता कि लक्ष्य दृश्य या तार्किक पेड़ पर है या नहीं। –

+0

@ErenErsonmez: 'ElementName' नाम को हल करने के लिए वर्तमान नेमस्कोप का उपयोग करता है, और नामकोप पेड़ पर निर्भर हैं जहां तक ​​मुझे पता है। –

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

यह वर्तमान जड़ objet की DataContext के लिए बाध्य सक्षम {विंडो, UserControl, ...

:}

नमूना उपयोग (दर्शनीय & दृश्यता viewmodel में गुण हैं)

<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

किसी कारण से मेरे लिए काम नहीं करता है ... 'बाइंडिंग एक्सप्रेशन पथ त्रुटि:' सत्यापन 'कॉलम दृश्यता' संपत्ति 'ऑब्जेक्ट' '' NameFixupToken '(हैशकोड = 55620207) पर नहीं मिली है। BindingExpression: पथ = ValidationColumnVisibility; DataItem = 'NameFixupToken' (हैशकोड = 55620207); लक्ष्य तत्व 'DataGridTextColumn' है (हैशकोड = 62066456); लक्षित संपत्ति 'दृश्यता' (प्रकार 'दृश्यता') 'है – Bartosz

संबंधित मुद्दे