2013-01-07 8 views
7

में डेटाफॉर्म के लिए डेटा टेम्पलेट के रूप में एक स्ट्रिंग का उपयोग करते समय ईवेंट हैंडलर मैं एक स्ट्रिंग का उपयोग करके प्रोग्रामेटिक रूप से डेटाफॉर्म के लिए कुछ xaml बनाने का प्रयास कर रहा हूं। मैं कॉम्बो बॉक्स दिखने के लिए मिल सकता हूं। लेकिन जब मैं स्ट्रिंग में "MouseLeftButtonUp" या "लोड" ईवेंट हैंडलर निर्दिष्ट कोड का उपयोग करने का प्रयास करता हूं; पेज इसमें जाने के बाद सफेद (कोई ध्यान देने योग्य त्रुटि) नहीं बदलेगा। कृपया नीचे प्रासंगिक कोड देखें।सिल्वरलाइट

 StringBuilder editTemplate = new StringBuilder(""); 
    editTemplate.Append("<DataTemplate "); 
    editTemplate.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' "); 
    editTemplate.Append("xmlns:toolkit='http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit' "); 
    editTemplate.Append("xmlns:navigation='clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation' "); 
    editTemplate.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' >"); 
    editTemplate.Append("<StackPanel>"); 
    editTemplate.Append(@" <toolkit:DataField Label='" + GetFieldWithoutNumber(theInfo, theDataContext) + "'>"); 
    /* Won't Work */ editTemplate.Append(@" <ComboBox MouseLeftButtonUp='ComboBox_MouseLeftButtonUp' />"); 
    /* Will Work */ editTemplate.Append(@" <ComboBox />"); 
    editTemplate.Append(@" </toolkit:DataField>"); 
    editTemplate.Append("</StackPanel></DataTemplate>"); 
    dynamicDataForm.EditTemplate = XamlReader.Load(editTemplate.ToString()) as DataTemplate; 
+1

यह मुझे आश्चर्य नहीं करता है, आपको डेटामैप्लेट बनाने के बाद प्रोग्राम हैंडलर प्रोग्राम प्रोग्रामिक रूप से हुक अप करना चाहिए। – slugster

+0

@slugster कृपया सलाह दें ... मैं यह कैसे कर सकता हूं? बस इसे एक नाम दें? – Kulingar

उत्तर

1

एक्सएएमएल में लगाए गए इवेंट हैंडलर को एक्सएएमएल फ़ाइल से जुड़े कोड-बैक में घोषित करने की आवश्यकता है। ResourceDictionary या XamlReader से लोड की गई किसी भी चीज़ के मामले में। लोड पर कोई कोड-पीछे नहीं हो सकता है, इसलिए ईवेंट हैंडलर XAML में सेट नहीं किए जा सकते हैं। सबसे आसान तरीका यह प्रतिबंध के आसपास पाने के लिए तार से अपने टेम्पलेट का निर्माण नहीं करने के लिए और सिर्फ अपने XAML फाइल के संसाधन अनुभाग है जिसे आप पसंद नहीं कर सकते हैं में यह घोषणा होगा:

Resources["MyTemplate"] as DataTemplate

टेम्पलेट प्राप्त करने के लिए और इसे कोड में असाइन करें जैसे आप यहां कर रहे हैं, या बस एक्सएएमएल में स्टेटिक रिसोर्स का उपयोग करें। जब तक यह इस कोड से जुड़ी एक ही एक्सएएमएल फ़ाइल में रहता है, तब तक आपके पास मौजूद ईवेंट हैंडलर को ठीक काम करना चाहिए। तारों के गतिशील भाग को बाइंडिंग का उपयोग करने के लिए भी बदलने की आवश्यकता होगी।

यदि आप XamlReader विधि से चिपकना चाहते हैं तो आपको हल करने के लिए 2 समस्याएं हैं।में नाम विशेषता:

  1. प्रतीक्षा गाया टेम्पलेट के अंदर ComboBox उदाहरण का पता जब तक टेम्पलेट ComboBox

ComboBox आप पहली बार यह एक एक्स देने की आवश्यकता को खोजने के लिए देखने के लिए प्रदान की गई है टेम्पलेट टेक्स्ट (आप वर्तमान में वहां इवेंट कोड को प्रतिस्थापित कर सकते हैं)। इसके बाद आपको दृश्य पेड़ में किसी आइटम को नाम से ढूंढने में सक्षम होना चाहिए। यह काफी सरल है और आप ऐसा करने के लिए example here पा सकते हैं।

सही समय पर इस कोड को कॉल करने के लिए आपको या तो OnApplyTemplate को ओवरराइड करने की आवश्यकता है, जो दुर्भाग्यवश काम नहीं करेगा अगर आप उपयोगकर्ता नियंत्रण जैसे कुछ में हैं, या किसी अन्य चाल का उपयोग तब तक चलने के लिए करें जब तक कि सभी नियंत्रण प्रदान नहीं किए जाते ।

DataTemplate template = Resources["MyTemplate"] as DataTemplate; 
dynamicDataForm.ContentTemplate = template; 

Dispatcher.BeginInvoke(() => 
{ 
    ComboBox button = FindVisualChildByName<ComboBox>(this, "MyControl"); 
    if (button != null) 
     button.MouseLeftButtonUp += (s, _) => MessageBox.Show("Click"); 
}); 

अपने मामले में यह अपने टेम्पलेट की तरह दिखता है में से पहले ही जिस स्थिति में renders एक संपादन राज्य के लिए स्विच करने के लिए इंतजार करना पड़ सकता है: यहाँ एक पूर्ण उदाहरण है कि एक निर्माता में जाने के लिए और खोज विधि ऊपर से जुड़ा हुआ उपयोग करता सकता है आपको ईवेंट को जोड़ने और अपने डेटाफॉर्म पर कुछ अन्य ईवेंट ढूंढने की आवश्यकता होगी जो तब होता है जब वह राज्य बदल जाता है।

1

एक समाधान DataForm की BeginningEdit घटना को संभालने और का उपयोग करें कि ComboBox के MouseLeftButtonUp घटना के लिए अपने ईवेंट हैंडलर सदस्यता के लिए है।

ऐसा करने के लिए, isEventWiredUp नामक एक निजी क्षेत्र के पीछे अपने कोड में जोड़ें। हम इस क्षेत्र का उपयोग इस ट्रैक का उपयोग करने के लिए करेंगे कि हमने घटना की सदस्यता ली है या घटना को एक से अधिक बार सब्सक्राइब करने से रोकें।

अगला, x:Name="..." अपने ComboBox पर विशेषता जोड़ें। हम combobox पर पाने के लिए इस नाम का उपयोग करें।

एक बार ऐसा करने के बाद, निम्नलिखित दो विधियां जोड़ें, जो करना चाहिए जो आप चाहते हैं। x:Name आप अपनी बता गया को दिया था साथ yourComboBoxName बदलें:

private void dynamicDataForm_BeginningEdit(object sender, CancelEventArgs e) 
    { 
     Dispatcher.BeginInvoke(OnBeginEdit); 
    } 

    private void OnBeginEdit() 
    { 
     if (!isEventWiredUp) 
     { 
      var combobox = dynamicDataForm.FindNameInContent("yourComboBoxName") as ComboBox; 
      if (combobox != null) 
      { 
       combobox.MouseLeftButtonUp += combobox_MouseLeftButtonUp; 
       isEventWiredUp = true; 
      } 
     } 
    } 

सदस्यता लें DataForm के BeginningEdit घटना के लिए इन दोनों तरीकों के पहले।

मुझे यह मानना ​​है कि मैं MouseLeftButtonUp ईवेंट को कॉम्बोबॉक्स पर आग लगाने में असमर्थ था। मुझे यकीन नहीं है कि ऐसा क्यों होता है, लेकिन यह कॉम्बोबॉक्स के साथ एक सामान्य समस्या प्रतीत होता है जो कि एक्सएएमएल का निर्माण करने के तरीके के कारण होता है। हालांकि, काम करने के लिए मैं कॉम्बोबॉक्स के SelectionChanged ईवेंट के लिए इवेंट हैंडलर प्राप्त करने में सक्षम था।

मैंने Dispatcher.BeginInvoke लाइन को OnBeginEdit विधि पर सीधे कॉल के साथ बदलने की भी कोशिश की, लेकिन मुझे पता चला कि यह दृष्टिकोण काम नहीं करता है। घटनाओं को काफी सही ढंग से तारित नहीं किया गया था; फिर, मुझे यकीन नहीं है क्यों।

+0

उत्तर जहां 13k प्रतिनिधि उपयोगकर्ता कहते हैं कि वे निश्चित नहीं हैं कि कुछ क्यों हो रहा है मुझे खुश बनाता है क्योंकि यह मेरी स्वच्छता को न्यायसंगत बनाता है। ;) आपके इनपुट के लिए धन्यवाद, मैं आपके और ल्यूक के सुझावों को देख रहा हूं। आपको जल्द ही बताएगा। :) लेकिन आपका आसान लगता है। – Kulingar

0

बल्कि सीधे घटना जोड़ने का काम करने की कोशिश कर रहा से, आप अपने घटनाओं

उदा अप बाध्य करने के लिए उपयोग कर सकते हैं अन्तरक्रियाशीलता

... 
editTemplate.Append("xmlns:i='clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity' "); 
... 
editTemplate.Append(@" 
<ComboBox> 
<i:Interaction.Triggers> 
    <i:EventTrigger EventName='MouseLeftButtonUp'> 

     <i:InvokeCommandAction Command='{Binding DataContext.YourCommand,                     
      RelativeSource={RelativeSource AncestorType=XXX}}' 
      CommandParameter='{Binding}'/> 

    </i:EventTrigger> 
</i:Interaction.Triggers> 
</ComboBox>"); 

आपको उस संदर्भ को प्राप्त करने के लिए कुछ पूर्वजों का उपयोग करना पड़ सकता है जिस पर आपके हैंडलर को परिभाषित किया गया है। मैं InvokeCommandAction के कस्टम कार्यान्वयन का उपयोग करता हूं; मूल रूप से System.Windows.Interactivity.InvokeCommandAction की एक प्रति लेकिन विस्तारित है ताकि यह ईवेंट को आदेश के लिए तर्क दे सके, तो आप ऐसा करना चाहेंगे।

0

XamlReader.Load को ईवेंट संलग्न करने की अनुमति नहीं है। इसलिए इस तकनीक का उपयोग गतिशील रूप से ईवेंट हैंडलर को संलग्न करने के लिए करें।

1- ईवेंट के बिना अपनी एक्सएमएल स्ट्रिंग लिखें- लेकिन उन नियंत्रणों की नाम संपत्ति लिखें।

2- लोड XamlReader.Load(str);

3- साथ स्ट्रिंग तो यह से DataTemplate की सामग्री लोड। Grid template = ((Grid)(dt.LoadContent()));

नोट: यहां GridDataTemplate में मूल नियंत्रण है।

4- उस नाम से नियंत्रण प्राप्त करें जिसे आप ईवेंट हैंडलर संलग्न करना चाहते हैं। Button img = (Button)template.FindName("MyButtonInDataTemplate");

मुझे उम्मीद है कि यह मदद करता है।