2010-08-04 15 views
84

से अभिभावक डेटाकॉन्टेक्स्ट एक्सेस करें मेरे पास ListBox है जो व्यूमोडेल पर बाल संग्रह से जुड़ा हुआ है।डेटा टेम्पलेट

<Style x:Key="curveSpeedNonConstantParameterCell"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
      ElementName=someParentElementWithReferenceToRootDataContext}" 
      Value="True"> 
      <Setter Property="Control.Visibility" Value="Hidden"></Setter> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 

मैं निम्नलिखित उत्पादन त्रुटि मिलती है: अगर मैं "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified" के लिए बाध्य अभिव्यक्ति बदल

System.Windows.Data Error: 39 : BindingExpression path error: 
'CurveSpeedMustBeSpecified' property not found on 
    'object' ''BindingListCollectionView' (HashCode=20467555)'. 
BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified; 
DataItem='Grid' (Name='nonConstantCurveParametersGrid'); 
target element is 'TextBox' (Name=''); 
target property is 'NoTarget' (type 'Object') 

तो यह काम करता है लिस्टबॉक्स आइटम माता पिता ViewModel पर एक संपत्ति के आधार पर एक DataTemplate में स्टाइल रहे हैं , लेकिन जब तक मूल उपयोगकर्ता नियंत्रण का डेटाकॉन्टेक्स्ट BindingListCollectionView है। यह स्वीकार्य नहीं है क्योंकि शेष उपयोगकर्ता नियंत्रण BindingList पर स्वचालित रूप से CurrentItem के गुणों से जुड़ा हुआ है।

मैं शैली के अंदर बाध्यकारी अभिव्यक्ति कैसे निर्दिष्ट कर सकता हूं ताकि यह अभिभावक डेटा संदर्भ संग्रह संग्रह या एक आइटम होने पर ध्यान दिए बिना काम करता हो?

उत्तर

135

मुझे सिल्वरलाइट में सापेक्ष स्रोत के साथ समस्याएं थीं। खोज और पढ़ने के बाद मुझे कुछ अतिरिक्त बाइंडिंग लाइब्रेरी का उपयोग किये बिना उपयुक्त समाधान नहीं मिला। लेकिन, यहां माता-पिता डेटाकॉन्टेक्स्ट तक पहुंच प्राप्त करने के लिए एक और तरीका है जिसका आप सीधे उस संदर्भ का संदर्भ दे रहे हैं जिसके बारे में आप डेटा संदर्भ जानते हैं। यह Binding ElementName उपयोग करता है और काफी अच्छी तरह से काम करता है, जब तक आप अपने खुद के नामकरण का सम्मान करते हैं और घटकों भर में templates/styles की भारी पुन: उपयोग की जरूरत नहीं है के रूप में:

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Button Content={Binding MyLevel2Property} 
       Command={Binding ElementName=level1Lister, 
         Path=DataContext.MyLevel1Command} 
       CommandParameter={Binding MyLevel2Property}> 
     </Button> 
    <DataTemplate> 
    <ItemsControl.ItemTemplate> 
</ItemsControl> 

यह भी काम करता है अगर आप Style/Template में बटन लगाना:

<Border.Resources> 
    <Style x:Key="buttonStyle" TargetType="Button"> 
    <Setter Property="Template"> 
     <Setter.Value> 
     <ControlTemplate TargetType="Button"> 
      <Button Command={Binding ElementName=level1Lister, 
            Path=DataContext.MyLevel1Command} 
        CommandParameter={Binding MyLevel2Property}> 
       <ContentPresenter/> 
      </Button> 
     </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    </Style> 
</Border.Resources> 

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <Button Content="{Binding MyLevel2Property}" 
       Style="{StaticResource buttonStyle}"/> 
    <DataTemplate> 
    <ItemsControl.ItemTemplate> 
</ItemsControl> 

पहले तो मैंने सोचा था कि माता-पिता तत्वों की x:Names एक टेम्प्लेटेड आइटम के भीतर से सुलभ नहीं हैं, लेकिन जब से मैं कोई बेहतर समाधान नहीं मिला, मैं सिर्फ कोशिश की, और यह ठीक काम करता है।

+0

मेरे पास मेरे प्रोजेक्ट में यह सटीक कोड है लेकिन यह व्यूमोडल्स को लीक कर रहा है (फाइनलाइज़र नहीं कहा जाता है, कमांड बाध्यकारी डेटाकॉन्टेक्स्ट को बनाए रखने लगता है)। क्या आप यह सत्यापित कर सकते हैं कि यह समस्या आपके लिए भी मौजूद है? –

+0

@ यह काम करता है, लेकिन क्या ऐसा करना संभव है ताकि यह सभी आइटम्स नियंत्रणों के लिए आग लगे जो समान टेम्पलेट को लागू करते हैं? नाम अद्वितीय है इसलिए हमें प्रत्येक के लिए एक अलग टेम्पलेट की आवश्यकता होगी, जब तक कि मुझे कुछ याद न हो। – Chris

+1

@ जुवे ने मेरी आखिरी अवहेलना की, मुझे इसे रिश्तेदार संसाधन का उपयोग करके खोजकर्ता के साथ मिलकर काम करना पड़ा और पूर्वजों द्वारा खोजना, (इसलिए नाम से नहीं खोजना)। मेरे मामले में मैं आइटम्स कंट्रोल्स का उपयोग दोहराता हूं जो प्रत्येक टेम्पलेट को कार्यान्वित करता है, इसलिए मेरा ऐसा दिखता है: कमांड = "{बाध्यकारी सापेक्ष स्रोत = {सापेक्ष स्रोत ढूँढें पूर्वज, पूर्वजों टाइप = {x: टाइप आइटम नियंत्रण}}, पथ = डेटाकॉन्टेक्स्ट। ओपन डॉक्यूमेंट बीटीएन कॉमांड}" – Chris

37

आप RelativeSource का उपयोग इस तरह, माता पिता के तत्व को खोजने के लिए कर सकते हैं -

Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
RelativeSource={RelativeSource AncestorType={x:Type local:YourParentElementType}}}" 

अधिक जानकारी के लिए this SO question देखें RelativeSource के बारे में।

+8

मुझे इसे काम करने के लिए 'मोड = FindAncestor' निर्दिष्ट करना था, लेकिन यह काम करता है और एमवीवीएम परिदृश्य में बहुत बेहतर है क्योंकि यह नामकरण नियंत्रण से बचाता है। 'बाध्यकारी =" {बाध्यकारी पथ = DataContext.CurveSpeedMustBe निर्दिष्ट, सापेक्ष स्रोत = {सापेक्ष स्रोत मोड = ढूँढें पूर्वजों, पूर्वजों टाइप = {x: स्थानीय टाइप करें: YourParentElementType}}} " – Aphex

+1

एक आकर्षण की तरह काम करता है <3 और उसे निर्दिष्ट नहीं करना था मोड, नेट 4.6.1 – user2475096

16

मैं WPF में इसी तरह कुछ करने के लिए कैसे खोज रहा था और मैं इस समाधान मिल गया:

<ItemsControl ItemsSource="{Binding MyItems,Mode=OneWay}"> 
<ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <StackPanel Orientation="Vertical" /> 
    </ItemsPanelTemplate> 
</ItemsControl.ItemsPanel> 
<ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <RadioButton 
      Content="{Binding}" 
      Command="{Binding Path=DataContext.CustomCommand, 
         RelativeSource={RelativeSource Mode=FindAncestor,  
         AncestorType={x:Type ItemsControl}} }" 
      CommandParameter="{Binding}" /> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 

मुझे आशा है कि यह किसी और के लिए काम करता है। मेरे पास एक डेटा संदर्भ है जो स्वचालित रूप से आइटम्सकंट्रोल पर सेट होता है, और इस डेटा संदर्भ में दो गुण होते हैं: MyItems - जो संग्रह है- और एक कमांड 'कस्टमकॉमैंड'। ItemTemplate के कारण DataTemplate का उपयोग कर रहा है, ऊपरी स्तर के DataContext सीधे पहुंच योग्य नहीं है। फिर माता-पिता के डीसी प्राप्त करने के लिए कामकाज एक सापेक्ष पथ का उपयोग करता है और ItemsControl प्रकार से फ़िल्टर करता है।

14

सापेक्ष स्रोत बनाम।ElementName

इन दो दृष्टिकोण एक ही परिणाम प्राप्त कर सकते हैं,

RelativeSrouce

Binding="{Binding Path=DataContext.MyBindingProperty, 
      RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 

इस विधि दृश्य में एक प्रकार खिड़की के नियंत्रण के लिए लग रहा है (इस उदाहरण में) पेड़ और जब इसे पाता है तो आप मूल रूप से Path=DataContext.... का उपयोग कर DataContext तक पहुंच सकते हैं। इस विधि के बारे में पेशेवर यह है कि आपको किसी नाम से बंधे रहने की आवश्यकता नहीं है और यह गतिशील है, हालांकि, आपके दृश्य पेड़ में किए गए परिवर्तन इस विधि को प्रभावित कर सकते हैं और संभवतः इसे तोड़ सकते हैं।

ElementName

Binding="{Binding Path=DataContext.MyBindingProperty, ElementName=MyMainWindow} 

इस विधि एक ठोस स्थिर Name को referes इसलिए जब तक आपके गुंजाइश इसे देख सकते हैं, तो आप fine.You अपने नामकरण परंपरा के लिए चिपके हुए किया जाना चाहिए नहीं तोड़ने के लिए कर रहे हैं पाठ्यक्रम की यह विधि। दृष्टिकोण qute सरल है और आपको अपनी विंडो/उपयोगकर्ता नियंत्रण के लिए Name="..." निर्दिष्ट करना है।

हालांकि सभी तीन प्रकार () एक ही काम करने में सक्षम हैं, लेकिन निम्नलिखित एमएसडीएन आलेख के अनुसार, प्रत्येक व्यक्ति को अपने विशेष क्षेत्र में बेहतर इस्तेमाल किया जाता है।

How to: Specify the Binding Source

प्लस प्रत्येक का संक्षिप्त विवरण एक पृष्ठ के तल पर तालिका में एक एक अधिक जानकारी के लिए लिंक का पता लगाएं।

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