2012-04-03 7 views
17

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

मैं इस समय इस तरह मेरे आदेशों बाध्यकारी हूँ:

Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MyCommand}" 

यह जहां यह गलत है (यह एक UserControl के अंदर है)

<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}" 
         Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}"> 

    <Button.ContextMenu> 
     <ContextMenu> 
      <MenuItem Header="Remove" CommandParameter="{Binding Name}" 
             Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.RemoveCommand}"/> 
     </ContextMenu> 
    </Button.ContextMenu> 
    ... 

बंधन की तरह काम करता है यह होना चाहिए पहले आदेश चला जाता है, लेकिन दूसरा कुछ भी करने से इंकार कर देता है। मैंने रिश्तेदार स्रोत के बजाय ElementName के माध्यम से इसे एक्सेस करने के लिए पूर्वजों के स्तर को बदलने और मेरे नियंत्रण का नामकरण करने का प्रयास किया है, लेकिन अभी भी कोई बदलाव नहीं है। यह कहता रहता है "संदर्भ के साथ बाध्यकारी के लिए स्रोत नहीं मिल रहा है ..."

मुझे क्या याद आ रही है?

+1

मैं जाँच करने के लिए होगा, लेकिन MenuItem एक अलग पेड़ में हो सकता है, तो यह UserControl के बाद से तकनीकी रूप से यह नहीं मिल सकता है पूर्वजों नहीं (स्नूप यह पुष्टि कर सकता है कि मुझे यह सही याद है या नहीं)। अन्य कमांड बाइंडिंग्स (जैसे कि बटन कंट्रोल के लिए कमांड) के लिए, आप कमान = "{बाइंडिंग पथ = कनेक्ट कॉमांड}" क्यों नहीं कर सकते? बटन को UserControl से DataContext को विरासत में लेना चाहिए और इसलिए पूरे सापेक्ष स्रोत/FindAncestor वाक्यविन्यास की आवश्यकता नहीं है। – MetalMikester

उत्तर

25

(संपादित करें) के बाद से आपके द्वारा उल्लेखित एक ItemsControl के टेम्पलेट में है, चीजों को अलग कर रहे हैं:

1) इस ब्लॉग से BindingProxy वर्ग (, जाओ और ब्लॉग को पढ़ने के इस रोचक जानकारी है के रूप में): How to bind to data when the DataContext is not inherited

मूल रूप से आइटम नियंत्रण (या ContextMenu) में तत्व दृश्य या तार्किक पेड़ का हिस्सा नहीं हैं, और इसलिए आपके UserControl का DataContext नहीं मिल सकता है। इस पर और अधिक लिखने के लिए मेरी माफ़ी, लेकिन लेखक ने कदम से कदम समझाकर एक अच्छा काम किया है, इसलिए कोई रास्ता नहीं है कि मैं कुछ ही पंक्तियों में पूरी व्याख्या दे सकता हूं।

2) कुछ इस तरह कार्य करें: (यदि आप इसे यह आपके नियंत्रण में काम करते हैं) बनाने के लिए एक सा अनुकूल करने के लिए हो सकता है:

एक। यह आपको एक स्टेटिक रिसोर्स का उपयोग कर UserControl DataContext तक पहुंच प्रदान करेगा:

<UserControl.Resources> 
<BindingProxy 
    x:Key="DataContextProxy" 
    Data="{Binding}" /> 
</UserControl.Resources> 

बी।

<Button.ContextMenu> 
<ContextMenu> 
    <MenuItem Header="Remove" CommandParameter="{Binding Name}" 
     Command="{Binding Path=Data.RemoveCommand, Source={StaticResource DataContextProxy}}"/> 
</ContextMenu> 

यह पेड़ और datagrids जैसी चीजों में हमारे लिए काम किया है: यह DataContextProxy (क) में परिभाषित का उपयोग करता है।

+0

समस्या यह है कि यह बटन किसी आइटम नियंत्रण आइटम टेम्पलेट का हिस्सा है। मेरे पास मॉडलों का एक संग्रह है जिसका उपयोग आइटम्स कंट्रोल '<आइटम्स कंट्रोल आइटमसोर्स =" {बाध्यकारी ऑलकनेक्शन} "के लिए बाध्यकारी के रूप में किया जाता है। /> यही कारण है कि कमांड को बाध्य करने का सरल तरीका काम नहीं करता क्योंकि वे उन मॉडलों में नहीं हैं (मुझे लगता है, यह अभी भी मेरे लिए अधिकतर जादू है) – Valyrion

+1

ओह, यह अलग है, लेकिन मुझे XamDataTree (Infragistics Tree Control) के साथ एक ही चीज़ से गुजरना पड़ा। मुझे आपके लिए जानकारी मिलनी चाहिए (अगर कोई और मेरे द्वारा समाधान से पहले कोई पोस्ट पोस्ट नहीं करता है) :) – MetalMikester

+0

@ बाबून की व्याख्या करने की देखभाल? – SZT

11

ContextMenu विभिन्न तार्किक पेड़ में है, यही कारण है कि सापेक्ष स्रोत काम नहीं करता है। लेकिन संदर्भ मेनू डेटाकॉन्टेक्स्ट को अपने "कंटेनर" से प्राप्त करता है, इस मामले में यह बटन है। यह सामान्य मामले में पर्याप्त है लेकिन आपके मामले में आपको आइटम्स कंट्रोल आइटम और आइटम्स कंट्रोल के दो "डेटा संदर्भ" की आवश्यकता है। मुझे लगता है कि आपके पास कोई अन्य विकल्प नहीं है, लेकिन अपने व्यू मॉडलों को एक में गठबंधन करें, कस्टम क्लास को आइटम कंट्रोल आइटम डेटा संदर्भ के रूप में उपयोग करने के लिए लागू करें और इसमें "नाम" और "निकालें आदेश" दोनों शामिल हों या आपके आइटम का दृश्य मॉडल RemoveCommand "प्रॉक्सी" को परिभाषित कर सकता है, एक

<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}" 
    Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" 
    Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}"> 
      <Button.ContextMenu> 
       <ContextMenu> 
        <MenuItem Header="Remove" 
        CommandParameter="{Binding Name}" 
        Command="{Binding Path=PlacementTarget.Tag.DataContext.RemoveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/> 
       </ContextMenu> 
      </Button.ContextMenu> 
+0

यह काम करता है। जब मैंने मूल कोड की कोशिश की तो मैं "डेटाकॉन्टेक्स्ट" के बजाय "डेटा" का उपयोग कर रहा था। मैं बाध्यकारीप्रोक्सी दृष्टिकोण के साथ रहूंगा हालांकि - वाक्यविन्यास थोड़ा कम भारी है, लेकिन हम सब कुछ कुछ अतिरिक्त वस्तुओं को ले जाने के लिए कभी-कभी टैग का उपयोग करते हैं और मैं उस बिंदु पर नहीं आना चाहता जहां हम उपयोग कर रहे हैं यह दृष्टिकोण और एक परिदृश्य में चला जहां टैग को दो अलग-अलग उद्देश्यों के लिए जरूरी है। हालांकि विकल्पों के लिए अच्छा है! – MetalMikester

3

एक मुश्किल मुद्दा है यही कारण है, यकीन है कि मामूली आप यहाँ एक त्वरित समाधान का मिलेगा, लेकिन यह है: कि माता-पिता कहेंगे आदेश आंतरिक

संपादित करें: मैं थोड़ा बबून के कोड बदल गया है, यह इस तरह से काम करना चाहिए नो-जादू-समाधान:

<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}" 
     Tag={Binding} 
     Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}">  
    <Button.ContextMenu> 
     <ContextMenu> 
      <MenuItem Header="Remove" 
         CommandParameter="{Binding Path=PlacementTarget.Tag.Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}" 
         Command="{Binding Path=PlacementTarget.Tag.RemoveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/> 
     </ContextMenu> 
    </Button.ContextMenu> 
... 

PlacementTarget (Button) के Tag का उपयोग करने के लिए यह उबलता है।

+0

दिलचस्प। मुझे यह देखने के लिए अपनी सामग्री पर कोशिश करनी होगी कि क्या यह बाइंडिंगप्रॉक्सी दृष्टिकोण को प्रतिस्थापित कर सकता है या नहीं। – MetalMikester

+0

वास्तव में मेरा मानना ​​है कि मैंने मूल रूप से एक एमएसडीएन उदाहरण से कहीं भी कटौती की है ... हालांकि याद नहीं कर सकता। –

+0

मैंने इसे हमारे XamDataTree आइटम टेम्पलेट में त्वरित प्रयास दिया और कोई नहीं - यह आदेश नहीं मिला। शायद यह स्लेडर के मामले में काम करेगा - आसपास के कोड के बिना कहना मुश्किल है। – MetalMikester

4

कोषदीम स्पॉट पर है, यह एक आकर्षण की तरह काम करता है !! धन्यवाद Koshdim

मैं अपने संदर्भ मेनू में फिट करने के लिए अपने कोड को संशोधित

<DataGrid 
     AutoGenerateColumns="False" 
     HeadersVisibility="Column" 
     Name="dgLosses" 
     SelectedItem="{Binding SelectedItem, Mode= TwoWay}" 
     AllowDrop="True" 
     ItemsSource="{Binding Losses}" 
     Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"> 


     <DataGrid.ContextMenu > 
      <ContextMenu > 
       <MenuItem Header="Move to Top  " Command="{Binding PlacementTarget.Tag.MoveToTopCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem> 
       <MenuItem Header="Move to Period 1" Command="{Binding PlacementTarget.Tag.MoveToPeriod1Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem> 
       <MenuItem Header="Move to Period 2" Command="{Binding PlacementTarget.Tag.MoveToPeriod2Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem> 
       <MenuItem Header="Move to Period 3" Command="{Binding PlacementTarget.Tag.MoveToPeriod3Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem>      
      </ContextMenu> 
     </DataGrid.ContextMenu> 
संबंधित मुद्दे