2009-06-12 9 views
5

मैंने एक कुंजी के आधार पर स्ट्रिंग्स का अनुवाद करने के लिए मार्कअप एक्सटेंशन बनाया है। उदाहरणमैं मार्कअप एक्सटेंशन के अंदर डेटाबेस के मान को कैसे हल करूं?

<TextBlock Text="{Translate myKey}" /> 

अब मैं अपनी चाबियाँ प्रदान करने के लिए नेस्टेड बाइंडिंग का उपयोग करने में सक्षम होना चाहता हूं। उदाहरण:

<TextBlock Text="{Translate {Binding KeyFromDataContext}}" /> 

जब मैं ऐसा करता हूं तो मुझे सिस्टम प्राप्त होता है। Windows.Data. बाइंडिंग ऑब्जेक्ट। ProvideValue बुला और ServiceProvider नीचे पारित करके मैं एक BindingExpression प्राप्त कर सकते हैं:

var binding = Key as Binding; 
if (binding == null) { 
    return null; 
} 
var bindingExpression = binding.ProvideValue(_serviceProvider) as BindingExpression; 
if (bindingExpression == null) { 
    return null; 
} 
var bindingKey = bindingExpression.DataItem; 

मैं इस bindingExpression प्राप्त कर सकते हैं, लेकिन DataItem संपत्ति रिक्त है। मैंने इस

<TextBlock Text="{Binding KeyFromDataContext}" /> 

और यह ठीक काम करता है जैसे मेरी बाध्यकारी का परीक्षण किया है।

कोई विचार?

उत्तर

0

toxvaerd's answer सार्वभौमिक नहीं है। यदि मूल बाध्यकारी पहले से ही कनवर्टर था तो यह टूट जाता है। या जब एक कनवर्टर लिखना संभव नहीं है।

एक बेहतर समाधान है। हम दो रचनाकार घोषित कर सकते हैं। एक बाध्यकारी उपयोग होने पर XAML द्वारा BindingBase को स्वीकार करने वाला दूसरा व्यक्ति कॉल किया जाएगा। बाध्यकारी के मूल्य को हल करने के लिए, हम एक निजी संलग्न संपत्ति घोषित कर सकते हैं। इसके लिए काम करने के लिए हमें मार्कअप एक्सटेंशन के लक्ष्य तत्व को जानने की आवश्यकता है।

एक पकड़ है: जब टेम्पलेट के अंदर मार्कअप एक्सटेंशन का उपयोग किया जाता है, तो कोई लक्ष्य तत्व नहीं है (जाहिर है)। ProvideValue() में return this का उपयोग करने के लिए इस मामले में आप supposed हैं - इस तरह टेम्पलेट लागू होने पर एक्सटेंशन को फिर से कॉल किया जाएगा।

public class TranslateExtension : MarkupExtension 
{ 
    private readonly BindingBase _binding; 

    public TranslateExtension(BindingBase binding) 
    { 
     _binding = binding; 
    } 

    public TranslateExtension(string key) 
    { 
     Key = key; 
    } 

    [ConstructorArgument("key")] 
    public string Key { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (_binding != null) 
     { 
      var pvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget)); 
      var target = pvt.TargetObject as DependencyObject; 

      // if we are inside a template, WPF will call us again when it is applied 
      if (target == null) 
       return this; 

      BindingOperations.SetBinding(target, ValueProperty, _binding); 
      Key = (string)target.GetValue(ValueProperty); 
      BindingOperations.ClearBinding(target, ValueProperty); 
     } 

     // now do the translation using Key 
     return ...; 
    } 

    private static readonly DependencyProperty ValueProperty = 
     DependencyProperty.RegisterAttached("Value", typeof(string), typeof(TranslateExtension)); 
} 
+0

क्या होगा यदि बाध्यकारी मान बदलता है, तो ProvideValue को फिर से कॉल नहीं किया जाता है? क्या इसका कोई समाधान है? – Haytam

+0

@ हैटम सवाल बाध्यकारी के मूल्य को हल करने के बारे में था। यदि आपको संदेह है कि यह बदल सकता है - तो आप इसके बजाय एक और बाध्यकारी वापस कर सकते हैं जो 'Value' से बांधता है और कनवर्टर का उपयोग करता है। – torvin

+0

क्या आप कृपया बता सकते हैं कि संलग्न संपत्ति कैसे काम करती है? मुझे हमेशा 'लक्ष्य' से 'null' मिल रहा है। GetValue()' ... – spacer

2

यह बाध्यकारी के मूल्य को प्राप्त करने के लिए संभव नहीं है। आपको ऐसा करने की कोशिश भी नहीं करनी चाहिए। डब्ल्यूपीएफ बाइंडिंग को हल करने और मुझ पर भरोसा करने के लिए कुछ फैंसी प्रतिबिंब का उपयोग करता है - आप स्वयं को आजमाने की कोशिश नहीं करना चाहते हैं।

मैं एक TranslateConverter कि अनुवाद का ध्यान रखा बनाया:

कि मन में साथ

वैसे भी, यह मैं क्या कर रहा है, जो वास्तव में एक अच्छा समाधान है समाप्त हो गया है में फिर

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    var key = value as string ?? parameter as string; 

    if (key != null) 
    { 
    // Do translation based on the key 

    } 
    return null; 
} 

मेरी ,

var binding = Key as Binding ?? new Binding{Mode = BindingMode.OneWay}; 
binding.Converter = new TranslateConverter(_targetObject, _targetProperty, Dictionary, Converter); 
binding.ConverterParameter = Key is Binding ? null : Key as string; 

return binding.ProvideValue(serviceProvider); 

इस तरह एक बाध्यकारी WPF द्वारा हल हो गई है और मूल्य के रूप में कनवर्टर करने के लिए पारित कर दिया है, जबकि एक सरल: TranslateExtension मैं बस यह करने के टेक्स्ट-की कनवर्टर को एक पैरामीटर के रूप में पास किया जाता है।

_targetObject और _targetProperty सेवा प्रदाता से प्राप्त किए जाते हैं।

+4

इसका क्या अर्थ है? एक डेटा बाध्यकारी एक और केवल एक मूल्य परिवहन और इसे अद्यतित रखने के लिए इसका उपयोग करें। बाध्यकारी कैसे मूल्य नहीं हो सकता है? मैं एक ही समाधान की तलाश में हूं लेकिन आपने अपने प्रश्न का उत्तर नहीं दिया है, आपने कुछ और जवाब दिया है। एक कनवर्टर मेरे लिए एक विकल्प नहीं है। – ygoe

+0

@ygoe मेरा [उत्तर] जांचें (https: // stackoverflow।कॉम/ए/480 90008/332528) – torvin

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