2011-06-15 7 views
5

स्थिति में लिपटे:एक्स: नाम काम नहीं कर रहा है, तो तत्व UserControl की सामग्री (Silverlight)

मैं एक "आवरण पैनल" UserControl इस तरह (नामस्थान और दृश्य विवरण संक्षिप्तता के लिए निकाला गया) है

<UserControl ...> 
<Grid x:Name="LayoutRoot" Background="White"> 
    <ContentPresenter x:Name="integratedPanelContent" Margin="5" /> 
</Grid> 
</UserControl> 

तब में कोड-पीछे मैं एक निर्भरता संपत्ति

public FrameworkElement PanelContent 
{ 
    get { return (FrameworkElement)GetValue(PanelContentProperty); } 
    set { SetValue(PanelContentProperty, value); } 
} 
public static readonly DependencyProperty PanelContentProperty = 
    DependencyProperty.Register("PanelContent", typeof(FrameworkElement), typeof(MyWrapperPanel), 
     new PropertyMetadata(null, OnPanelContentChanged)); 

private static void OnPanelContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ((MyWrapperPanel)d).OnSetContentChanged(e); 
} 

protected virtual void OnSetContentChanged(DependencyPropertyChangedEventArgs e) 
{ 
    if (PanelContent != null) 
     integratedPanelContent.Content = PanelContent; 
} 

अब मैं में किसी भी सामग्री को लपेट कर सकते हैं पंजीकृत किया है मेरे नियंत्रण:

जब भी मैं codebehind में संदर्भ tbxNothing इस्तेमाल करने की कोशिश, प्रणाली NullReferenceException फेंकता है क्योंकि tbxNothing है, हालांकि के रूप में एक संदर्भ मौजूद है, को इंगित नहीं करता:

<my:MyWrapperPanel x:Name="myWrap"> 
    <my:MyWrapperPanel.PanelContent> 
     <TextBlock x:Name="tbxNothing" Text="Nothing" /> 
    </my:MyWrapperPanel.PanelContent> 
</my:MyWrapperPanel> 

समस्या का विवरण टेक्स्टब्लॉक XAML में परिभाषित किया गया है, लेकिन null है।

संभावित (लेकिन असुविधाजनक) वैकल्पिक हल:

एक समाधान है जहां मैं TextBlock से x:Name निकालने के लिए, और फिर मैं स्पष्ट रूप निजी TextBlock tbxNothing बुलाया परिभाषित नहीं है। तब OnNavigatedTo ईवेंट हैंडलर में मैं मान असाइन निम्नलिखित तरीके:

tbxNothing = myWrap.PanelContent as TextBlock; 

यह काम करता है लेकिन क्योंकि अगर एक सामग्री एक StackPanel कि चाहता था नियंत्रण होता है, यह करने के लिए एक सही तरीका नहीं है, मैं करना होगा मुझे जो चाहिए वह ढूंढने के लिए पेड़ को पार करें, जो बेहद असुविधाजनक है।

प्रश्न:

क्यों है TextBlock अब दिखाई एक उपयोगकर्ता नियंत्रण (वैसे वर्णित) में जब लिपटे, और कैसे अपने एक्स से इसे पाने के लिए: में कोड-पीछे का नाम?

उत्तर

6

समस्या यह है कि आपकी पैनल सामग्री दो मल के बीच गिर रही है। एक तरफ "tbxNothing" नाम वाली सामग्री मुख्य पृष्ठ के नामस्थान में बनाई गई है। हालांकि यह उस बिंदु पर ऑब्जेक्ट पेड़ में नहीं जोड़ा गया है। दूसरी तरफ MyWrapperPanel UserControl होने का अपना नामस्थान है और इसके नीचे ऑब्जेक्ट पेड़ में है कि उस नाम के साथ आइटम "tbxNothing" जोड़ा गया है। मुख्य पृष्ठ पर FindName को MyWrapperPanel के अंदर कुछ भी नहीं मिलेगा क्योंकि इसका अपना नामस्थान है और MyWrapperPanel पर FindName "tbxNothing" नहीं मिलेगा क्योंकि यह इसके नामस्थान में वास्तव में मौजूद नहीं है (वास्तव में मुख्य पृष्ठ में बनाया गया है)।

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

public class MyWrapperPanel : ContentControl 
{ 
    public MyWrapperPanel() 
    { 
     this.DefaultStyleKey = typeof(MyWrapperPanel); 
    } 
} 

फिर विषयों/जेनेरिक में।शैली XAML इस तरह दिखना सकते हैं: -

<Style TargetType="local:MyWrapperPanel"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:MyWrapperPanel"> 
       <Grid> 
        <ContentPresenter /> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

आपका मुख्य पृष्ठ XAML दिखाई देगा: -

<my:MyWrapperPanel x:Name="myWrap"> 
    <TextBlock x:Name="tbxNothing" Text="Nothing" /> 
</my:MyWrapperPanel> 

ध्यान दें कि ContentControl से पाने आप एक Content संपत्ति देता है जो करने के लिए ContentPresenter ऑटो जादुई तारों ।

+0

मैं निश्चित रूप से यह कोशिश कर रहा हूं, लेकिन मुझे एक चीज़ के बारे में अनिश्चितता है। MyWrapperPanel के कुछ तत्व इंटरैक्टिव हैं, इसलिए मैंने पहले कुछ ईवेंट हैंडलर को मेरे UserControl के कोड-पीछे में रखा है। यदि मैं टेम्पलेट के माध्यम से तत्वों को परिभाषित करता हूं, तो मैं कस्टम तर्क करने के लिए टेम्पलेट से विशिष्ट तत्वों तक कैसे पहुंच सकता हूं? एक्स निर्दिष्ट करना होगा: टेम्पलेट तत्वों पर नाम FindName() के माध्यम से नियंत्रण के कोडबेंड में दिखाई दे सकता है या टेम्पलेट परिभाषित तत्वों पर कस्टम तर्क प्राप्त करने का एक बेहतर तरीका है? –

+0

@kornelijepetak: हाँ आप टेम्पलेट में 'x: name' का उपयोग कर सकते हैं हालांकि कस्टम टेम्पलेटेड नियंत्रण के भीतर कोड से उन्हें' GetTemplateChild' संरक्षित विधि का उपयोग करके एक्सेस किया जाता है। 'FindName' अब' UserControl' के नामस्थान पर काम करेगा, यही कारण है कि यह दृष्टिकोण आपकी प्रारंभिक समस्या को हल करता है। – AnthonyWJones

+0

लेकिन क्या मुझे मुख्य पृष्ठ में FindName() का उपयोग करने की आवश्यकता है या क्या मैं tbxNothing संदर्भ का उपयोग करके टेक्स्टब्लॉक तक पहुंच सकता हूं? –

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