2011-09-20 13 views
7

से कस्टम मार्कअप एक्सटेंशन सेट करें आप कोड से कस्टम MarkupExtension कैसे सेट करते हैं?कोड

आप आसानी से Xaml से सेट कर सकते हैं। यह Binding और DynamicResource के लिए जाता है। उपयोग textBox.SetBinding या BindingOperations.SetBinding

Binding binding = new Binding("MyFontSize"); 
BindingOperations.SetBinding(textBox, TextBox.FontSizeProperty, binding); 
  • DynamicResource:

    <TextBox FontSize="{Binding MyFontSize}" 
         Style="{DynamicResource MyStyle}" 
         Text="{markup:CustomMarkup}"/> 
    

    कोड के माध्यम से ही मान की स्थापना के पीछे एक छोटे से अलग दृष्टिकोण

    1. बाइंडिंग की आवश्यकता है SetResourceReference

      का उपयोग करें
      textBox.SetResourceReference(TextBox.StyleProperty, "MyStyle"); 
      
    2. CustomMarkup: मैं कोड से एक कस्टम MarkupExtension कैसे सेट करूँ? मैं ProvideValue बुलाना चाहिए और यह कि मामला, मैं कैसे एक IServiceProvider? *

      CustomMarkupExtension customExtension = new CustomMarkupExtension(); 
      textBox.Text = customExtension.ProvideValue(??); 
      

    की पकड़ मैंने पाया आश्चर्यजनक रूप से इस विषय पर थोड़ा हां, तो यह किया जा सकता है मिलता है?


    एचबी। ने इस प्रश्न का उत्तर दिया है। मैं यहां कुछ विवरण जोड़ रहा हूं कि मैं ऐसा क्यों करना चाहता था। मैंने निम्नलिखित समस्या के लिए एक समाधान बनाने की कोशिश की।

    समस्या यह है कि आप Binding से प्राप्त नहीं कर सकते हैं और इसे सील कर दिए जाने के बाद ProvideValue ओवरराइड कर सकते हैं। आपको इसके बजाय ऐसा कुछ करना होगा: A base class for custom WPF binding markup extensions। लेकिन फिर समस्या यह है कि जब आप Binding को Setter पर वापस लेते हैं तो आपको अपवाद मिलता है, लेकिन Style के बाहर यह ठीक काम करता है।

    मैं कई स्थानों है कि आप MarkupExtension ही लौटना चाहिए अगर TargetObject एक Setter है एक बार यह एक वास्तविक FrameworkElement करने के लिए लागू किया जा रहा है और इस समझ में आता है यह reeavaluate को अनुमति देने के लिए पढ़ा है।

    हालांकि, कि केवल काम करता है जब TargetProperty प्रकार object की है, अन्यथा अपवाद वापस आ गया है। यदि आप BindingBase के लिए स्रोत कोड देखते हैं तो आप देख सकते हैं कि यह वास्तव में ऐसा करता है लेकिन ऐसा लगता है कि ढांचे में कुछ गुप्त घटक हैं जो इसे काम करता है।

  • उत्तर

    6

    मुझे लगता है कि कोई कोड-बराबर होती है, सेवाओं XAML के माध्यम से ही उपलब्ध हैं। MSDN से:

    मार्कअप एक्सटेंशन में केवल एक वर्चुअल विधि है, ProvideValue।इनपुट सेवाप्रदाता पैरामीटर यह है कि जब एक्सएएमएल प्रोसेसर द्वारा मार्कअप एक्सटेंशन को कॉल किया जाता है तो सेवाओं को कार्यान्वयन के लिए कैसे सूचित किया जाता है।

    +1

    हे एचबी। हां, मैंने इसे भी पढ़ा, हालांकि मैं उम्मीद कर रहा था कि अभी भी एक रास्ता होगा। यह बहुत बुरी खबर है और कस्टम 'मार्कअप एक्सटेंशन' अर्ध-कार्यशील अवधारणा की तरह दिखता है। यदि लक्ष्यप्रोपर्टी प्रकार 'ऑब्जेक्ट' नहीं है, तो उन्हें 'स्टाइल' 'सेटर' में उपयोग नहीं किया जा सकता है, इसलिए मैं इस मुद्दे को अपने आप को एक संलग्न व्यवहार में जोड़कर काम करने की उम्मीद कर रहा था लेकिन वहां वह योजना है। वैसे भी, आपके उत्तर के लिए धन्यवाद –

    +0

    @Meleak: ठीक है, जैसा कि नाम कहता है मार्कअप एक्सटेंशन मार्कअप का विस्तार करता है, वे वास्तव में कोड में उपयोग करने के लिए नहीं हैं। मैं रास्ते में Setters में MarkupExtensions के उपयोग के साथ किसी भी समस्या का पुनरुत्पादन नहीं कर सकता। –

    +1

    मैं मानता हूं, यह नाम से निहित है, अभी भी एक तरह से उम्मीद है :) मैं अपनी टिप्पणी में वास्तव में स्पष्ट नहीं था, समस्या तब होती है जब आप 'सेटर' को 'बाध्यकारी' मान प्रदान करते हैं। आपने प्रश्न का उत्तर दिया है और मैं आपका उत्तर स्वीकार करता हूं। कुछ प्रश्नों को जोड़ा गया कि मैं अपने प्रश्न –

    2

    This Silverlight TV show इस मुद्दे पर कुछ प्रकाश डाल सकता है। मुझे याद है कि उन्हें कुछ कोड नमूने दिखाए जा सकते हैं जो सहायक हो सकते हैं।

    +0

    में ऐसा क्यों करना चाहता था इस विशेष विषय पर कुछ भी नहीं मिला लेकिन एक सुखद लिंक के लिए +1 :) –

    +0

    क्षमा करें, इससे मदद नहीं मिली, लेकिन हाँ, यह एक सुखद शो था। –

    1

    एचबी के रूप में। इंगित किया गया, MarkupExtension का उद्देश्य केवल एक्सएएमएल के भीतर उपयोग किया जाना है।

    क्या Binding अनूठा बनाता है कि यह वास्तव में MarkupExtension है जो यह संभव विस्तार वाक्य रचना {Binding ...} या पूर्ण मार्कअप <Binding>...</Binding> का उपयोग करें और कोड में इसका इस्तेमाल करने के लिए बनाता है से निकला है।

    हालांकि, आप हमेशा मध्यस्थ वस्तु (BindingOperations के समान कुछ) बनाने का प्रयास कर सकते हैं जो जानता है कि अपने कस्टम मार्कअप एक्सटेंशन का उपयोग कैसे करें और इसे DependencyObject पर लक्षित करें।

    ऐसा करने के लिए, मुझे विश्वास है कि आपको XamlSetMarkupExtensionAttribute (.NET 4 के लिए) या IReceiveMarkupExtension इंटरफ़ेस (.NET 3.x के लिए) का उपयोग करने की आवश्यकता होगी। मुझे पूरी तरह से यकीन नहीं है कि विशेषता और/या इंटरफ़ेस का उपयोग कैसे करें, लेकिन यह आपको सही दिशा में इंगित कर सकता है।

    +0

    मुझे यकीन नहीं है कि "बाध्यकारी अद्वितीय बनाता है" से आपका क्या मतलब है, यह 'मार्कअप एक्सटेंशन' से निकला है और इसलिए मेरा कस्टम 'मार्कअप एक्सटेंशन' भी है, मैं अंतर नहीं देख सकता। आपके उत्तर के दूसरे भाग के लिए आप सही रास्ते पर प्रतीत होते हैं, यह जानना अच्छा है। +1 –

    +0

    मैं यह बताने की कोशिश कर रहा था कि 'बाइंडिंग' 'MyClassExtension' के साथ 'MyClass' बनाने के सामान्य सम्मेलन का पालन नहीं करता है जो आमतौर पर मार्कअप में' MyClass' प्रकार का मान प्रदान करेगा। – sellmeadog

    +0

    अभी भी सुनिश्चित नहीं है कि मैं अनुसरण करता हूं लेकिन किसी भी 'मार्कअप एक्सटेंशन' को '{मार्कअप: कस्टम} 'और' <मार्कअप: कस्टम /> 'जैसे सेट किया जा सकता है। वैसे भी, इससे कोई फर्क नहीं पड़ता। मैंने –

    4

    क्या एक विकल्प के रूप में इस के बारे में है, यह कोड में उत्पन्न होता है लेकिन जरूरी नहीं कि के रूप में XAML के रूप में सुंदर नहीं:

     var markup = new CustomMarkup(); 
         markup.ProvideValue(new Target(textBox, TextBox.TextProperty)); 
    

    लक्ष्य के लिए कार्यान्वयन बस है:

    public struct Target : IServiceProvider, IProvideValueTarget 
    { 
        private readonly DependencyObject _targetObject; 
        private readonly DependencyProperty _targetProperty; 
    
        public Target(DependencyObject targetObject, DependencyProperty targetProperty) 
        { 
         _targetObject = targetObject; 
         _targetProperty = targetProperty; 
        } 
    
        public object GetService(Type serviceType) 
        { 
         if (serviceType == typeof(IProvideValueTarget)) 
          return this; 
         return null; 
        } 
    
        object IProvideValueTarget.TargetObject { get { return _targetObject; } } 
        object IProvideValueTarget.TargetProperty { get { return _targetProperty; } } 
    } 
    

    केवल बात यह है कि बनी हुई है XAML ऑब्जेक्ट मॉडल से 'कस्टममार्कअप' पर संदर्भ प्राप्त करने की क्षमता है। उपर्युक्त के साथ आपको इसके संदर्भ में लटकने की आवश्यकता है।

    +0

    ग्रेट ने मुझे मार्कअप एक्सटेंशन का उपयोग करके कोड पर ध्यान केंद्रित करने में मदद की –

    3

    अपने मार्कअप विस्तार काफी सरल है और एक बाध्यकारी बनाता है और ProvideValue से परिणाम देता है() तो आप एक सरल सहायक विधि जोड़ सकते हैं:

    public class CommandExtension : MarkupExtension 
    { 
        public CommandExtension(string name) 
        { 
         this.Name = name; 
        } 
    
        public string Name { get; set; } 
    
        public override object ProvideValue(IServiceProvider serviceProvider) 
        { 
         return GetBinding(this.Name).ProvideValue(serviceProvider); 
        } 
    
        static Binding GetBinding(string name) 
        { 
         return new Binding("Commands[" + name + "]") { Mode = BindingMode.OneWay }; 
        } 
    
        public static void SetBinding(DependencyObject target, DependencyProperty dp, string commandName) 
        { 
         BindingOperations.SetBinding(target, dp, GetBinding(commandName)); 
        } 
    } 
    

    और फिर कोड में, तुम बस CommandExtension कॉल कर सकते हैं। BindingOperations.SetBinding() के बजाय SetBinding()।

    जाहिर है, यदि आप इससे कुछ अधिक जटिल कर रहे हैं तो यह समाधान उचित नहीं हो सकता है।

    0

    मैं कैसे कोड से एक कस्टम MarkupExtension सेट करूँ?

    आप इसे संशोधित कर सकते हैं करते हैं तो बस अलग SomeMethod में तर्क जो अकेले और/या ProvideValue से कहा जा सकता है निकालें।तब

    textBox.Text = customExtension.ProvideValue(??); 
    

    के बजाय

    तुम सिर्फ इसे कहते

    customExtension.SomeMethod(textBox, TextBox.TextProperty); 
    

    अक्सर हम कस्टम संपत्ति एक्सटेंशन (XAML में इस तरह प्रयोग किया जाता) पैदा कर रहे:

    <TextBox Text="{local:SomeExtension ...}" /> 
    

    यह इस तरह लिखा जा सकता है:

    public class SomeExtension : MarkupExtension 
    { 
        public override object ProvideValue(IServiceProvider serviceProvider) 
        { 
         var provider =  serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
         var target = provider.TargetObject as DependencyObject; 
         var property = provider.TargetProperty as DependencyProperty; 
         // defer execution if target is data template 
         if (target == null) 
          return this; 
         return SomeMethod(target, property); 
        } 
    
        public object SomeMethod(DependencyObject target, DependencyProperty property) 
        { 
         ... // do something 
        } 
    } 
    

    के बाद मुझे एहसास हुआ कि वहाँ कभी कभी कोड से मार्कअप एक्सटेंशन मैं हमेशा उनसे इस तरह से लिखने के लिए कोशिश कर रहा हूँ उपयोग करने के लिए एक आवश्यकता है।