2009-08-27 16 views
111

जहां पदानुक्रम में प्रत्येक MenuItem अपने Command संपत्ति एक RoutedCommand मैं परिभाषित किया है करने के लिए सेट है मैं एक Menu है मजबूर करने के लिए। संबंधित CommandBindingCanExecute के मूल्यांकन के लिए कॉलबैक प्रदान करता है जो प्रत्येक MenuItem की सक्षम स्थिति को नियंत्रित करता है।WPF - कैसे एक कमान फिर से मूल्यांकन करने के लिए 'CanExecute' अपनी CommandBindings के माध्यम से

यह लगभग काम करता है। मेनू आइटम प्रारंभ में सही सक्षम और अक्षम राज्यों के साथ आते हैं। हालांकि जब मेरा CanExecute कॉलबैक परिवर्तन का उपयोग करता है, तो मुझे इस नए राज्य को UI में प्रतिबिंबित करने के लिए मेरे कॉलबैक से परिणाम का दोबारा अनुरोध करने के लिए आदेश की आवश्यकता है।

इस के लिए RoutedCommand या CommandBinding पर कोई सार्वजनिक विधि प्रतीत नहीं होती है।

ध्यान दें कि जब मैं नियंत्रण में क्लिक या टाइप करता हूं तो कॉलबैक दोबारा उपयोग किया जाता है (मुझे लगता है कि यह इनपुट पर ट्रिगर हुआ है क्योंकि माउस-ओवर रीफ्रेश नहीं करता है)।

उत्तर

149
नहीं

किताब में सबसे सुंदर है, लेकिन आप सभी commandbinding रद्द करने के लिए CommandManager उपयोग कर सकते हैं:

CommandManager.InvalidateRequerySuggested(); 

किसी को जो बाद में इस भर आता है के लिए MSDN

+0

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

+4

मैंने अपना वोट दोबारा लागू करने के लिए अपना जवाब संपादित किया। मैंने संपादन में कुछ भी नहीं बदला। एक बार फिर धन्यवाद। –

+0

हाहा ठीक :) धन्यवाद! – Arcturus

72

बारे में अधिक जानकारी देखें; यदि आप एमवीवीएम और प्रिज्म का उपयोग करते हैं, तो प्रिज्म DelegateCommandICommand के कार्यान्वयन को करने के लिए .RaiseCanExecuteChanged() विधि प्रदान करता है।

+10

यह पैटर्न अन्य एमवीवीएम पुस्तकालयों में भी मिलता है, जैसे एमवीवीएम लाइट –

+1

प्रिज्म के विपरीत, एमवीवीएम लाइट वी 5 का स्रोत कोड इंगित करता है कि 'RaiseCanExecuteChanged()' बस 'CommandManager.InvalidateRequerySuggested() 'को कॉल करता है। – Peter

+3

डब्ल्यूपीएफ में एमवीवीएम लाइट के लिए एक साइड नोट, आपको नामस्थान GalaSoft.MvvmLight.CommandWpf का उपयोग करने की आवश्यकता है क्योंकि GalaSoft.MvvmLight.Command परेशानी का कारण बन जाएगा http://www.mvvmlight.net/installing/changes#v5_0_2 – fuchs777

21

मैं CommandManager.InvalidateRequerySuggested(); का उपयोग नहीं कर सका क्योंकि मुझे प्रदर्शन हिट मिल रही थी।

मैंने MVVM Helper के प्रतिनिधि आदेश का उपयोग किया है, जो नीचे जैसा दिखता है (मैंने इसे हमारे req के लिए थोड़ा सा tweaked किया है)। आप वीएम

से command.RaiseCanExecuteChanged() कॉल करने के लिए
public event EventHandler CanExecuteChanged 
{ 
    add 
    { 
     _internalCanExecuteChanged += value; 
     CommandManager.RequerySuggested += value; 
    } 
    remove 
    { 
     _internalCanExecuteChanged -= value; 
     CommandManager.RequerySuggested -= value; 
    } 
} 

/// <summary> 
/// This method can be used to raise the CanExecuteChanged handler. 
/// This will force WPF to re-query the status of this command directly. 
/// </summary> 
public void RaiseCanExecuteChanged() 
{ 
    if (canExecute != null) 
     OnCanExecuteChanged(); 
} 

/// <summary> 
/// This method is used to walk the delegate chain and well WPF that 
/// our command execution status has changed. 
/// </summary> 
protected virtual void OnCanExecuteChanged() 
{ 
    EventHandler eCanExecuteChanged = _internalCanExecuteChanged; 
    if (eCanExecuteChanged != null) 
     eCanExecuteChanged(this, EventArgs.Empty); 
} 
+0

यह बेहतर काम करता है मेरे लिए। धन्यवाद। –

+2

बस एक एफवाईआई मैंने कमांडमैनेजर पर टिप्पणी की। REequerySuggested + = value; मुझे किसी कारण से मेरे CanExecute कोड का निकट निरंतर/लूपिंग मूल्यांकन मिल रहा था। अन्यथा समाधान अपेक्षित के रूप में काम किया। धन्यवाद! – robaudas

2

मैं आदेशों पर संपत्ति निर्भरता, यहाँ लिंक है कि आप इस तरह एक आदेश होने पहुंच जाएंगे लिए https://stackoverflow.com/a/30394333/1716620

धन्यवाद संभालने के लिए एक समाधान लागू किया है:

this.SaveCommand = new MyDelegateCommand<MyViewModel>(this, 
    //execute 
    () => { 
     Console.Write("EXECUTED"); 
    }, 
    //can execute 
    () => { 
     Console.Write("Checking Validity"); 
     return PropertyX!=null && PropertyY!=null && PropertyY.Length < 5; 
    }, 
    //properties to watch 
    (p) => new { p.PropertyX, p.PropertyY } 
); 
4

आप अपने खुद के वर्ग को लागू करता है कि ICommand आप मैन्युअल से अधिक की जरूरत किया जाना चाहिए ताज़ा पर भरोसा करने के लिए मजबूर कर रहा स्वत: स्थिति अद्यतन का एक बहुत खो सकते हैं लुढ़का है। यह InvalidateRequerySuggested() भी तोड़ सकता है। समस्या यह है कि एक साधारण ICommand कार्यान्वयन नए आदेश को CommandManager से जोड़ने में विफल रहता है।

समाधान निम्न का उपयोग करने के लिए है:

public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public void RaiseCanExecuteChanged() 
    { 
     CommandManager.InvalidateRequerySuggested(); 
    } 

इस तरह ग्राहकों बल्कि अपने वर्ग से CommandManager से संलग्न है और ठीक से आदेश स्थिति परिवर्तन में भाग ले सकते।

+0

सीधे, बिंदु पर, और लोगों को अपने आईसीओएमएंड कार्यान्वयन पर नियंत्रण रखने की अनुमति देता है। –

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