2009-03-16 12 views

उत्तर

22

अंतर यह है कि रिलेकॉमैंड प्रतिनिधियों को स्वीकार कर सकता है। आप ViewModel के बाहर RelayCommand को परिभाषित कर सकते हैं। व्यूमोडेल तब कमांड में प्रतिनिधियों को जोड़ सकता है जब यह एक यूआई ऑब्जेक्ट को नियंत्रण जैसे कमांड बनाता है और बाध्य करता है। बदले में प्रतिनिधियों को व्यूमोडेल के निजी चर का उपयोग कर सकते हैं क्योंकि उन्हें व्यू मॉडल के दायरे में परिभाषित किया गया है।

इसका उपयोग व्यूमोडेल में निहित कोड की मात्रा को कम करने के लिए किया जाता है क्योंकि प्रवृत्ति व्यूमोडेल के अंदर एक नेस्टेड क्लास के रूप में रूटेड कमांड को परिभाषित करना है। दोनों की कार्यक्षमता अन्यथा समान है।

67

RoutedCommand WPF का हिस्सा है, जबकि RelayCommand एक WPF शिष्य, जोश स्मिथ द्वारा बनाया गया था;)।

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

34

RelayCommand और RoutedCommand MVVM में के उपयोग के बारे में मेरे लिए मुख्य अंतर यह है:

कोड के स्थान

RelayCommand आप किसी भी वर्ग में आदेश लागू करने के लिए (अनुमति देता है ICommand प्रॉपर्टी के रूप में प्रतिनिधियों के साथ), जो तब पारंपरिक रूप से नियंत्रण के लिए डेटाबेस है, जो आदेश को आमंत्रित करता है। यह वर्ग व्यूमोडेल है। यदि आप रूटेड कमांड का उपयोग करते हैं, तो आपको नियंत्रण के कोडबेहिंड में कमांड से संबंधित विधियों को लागू करना होगा, क्योंकि विधियां कमांड बाइंडिंग-तत्व के गुणों द्वारा निर्दिष्ट की गई हैं। मान लीजिए कि सख्त एमवीवीएम का मतलब है कि "खाली" कोडबेंड फ़ाइल है, वास्तव में एमवीवीएम के साथ मानक रूटेड कमांड का उपयोग करने की कोई संभावना नहीं है।

क्या रुपये Conley ने कहा, कि RelayCommand आप को परिभाषित करने के ViewModel बाहर RelayCommand सही है की अनुमति देता है, लेकिन सब से पहले यह आप अंदर यह परिभाषित करने के लिए ViewModel, जो RoutedCommand नहीं है की अनुमति देता है।

रूटिंग

दूसरी ओर, RelayCommands जो नहीं के रूप में अपने इंटरफेस के लिए एक एकल ViewModel पर आधारित है एक समस्या है, जब तक है (जैसा कि पहले भी कहा) पेड़ के माध्यम से मार्ग का समर्थन नहीं करते। यदि ऐसा नहीं है, उदाहरण के लिए यदि आपके पास अपने स्वयं के दृश्य के साथ आइटम का संग्रह है मॉडल और माता-पिता तत्व के प्रत्येक आइटम के लिए बच्चे के एक कमांड को एक बार में खोलना चाहते हैं, तो आपको रूटिंग का उपयोग करना होगा (कंपोजिट कमांड देखें) ।

सब कुछ, मैं कहूंगा कि मानक रूटेड कमांड सख्त एमवीवीएम में प्रयोग योग्य नहीं हैं। रिलेकॉमैंड्स एमवीवीएम के लिए बिल्कुल सही हैं लेकिन रूटिंग का समर्थन नहीं करते हैं, जिन्हें आपको आवश्यकता हो सकती है।

+0

आपके स्पष्टीकरण में अतिरिक्त गहराई और कंपोजिट कमांड के संदर्भ के लिए धन्यवाद - इससे मुझे यह देखने में मदद मिली कि वे कहां फिट बैठते हैं। –

13

मैं तर्क दूंगा कि रूटेड कमांड सख्त एमवीवीएम में पूरी तरह से कानूनी हैं। हालांकि रिलेकॉमैंड्स अक्सर अपनी सादगी के लिए बेहतर होते हैं, रूटेड कॉमांड कभी-कभी संगठनात्मक फायदे प्रदान करते हैं।उदाहरण के लिए, आप अंतर्निहित ViewModels पर सीधे उस आदेश को बेनकाब किए बिना किसी साझा आईसीओएमएंड इंस्टेंस से कनेक्ट करने के लिए कई अलग-अलग विचारों को प्राप्त कर सकते हैं।

एक साइड नोट के रूप में, याद रखें कि सख्त एमवीवीएम कोड-बैक के उपयोग को प्रतिबंधित नहीं करता है। यदि यह सत्य थे तो आप अपने विचारों में कस्टम निर्भरता गुणों को कभी परिभाषित नहीं कर सकते!

आदेश एक सख्त MVVM ढांचे के भीतर एक RoutedCommand उपयोग करने के लिए आप इन चरणों का पालन कर सकता है में:

  1. अपने कस्टम आदेश के लिए एक स्थिर RoutedCommand उदाहरण घोषित। यदि आप एप्लिकेशन कमांड क्लास से पूर्वनिर्धारित कमांड का उपयोग करने की योजना बना रहे हैं तो आप इस चरण को छोड़ सकते हैं। उदाहरण के लिए:

    public static class MyCommands { 
        public static RoutedCommand MyCustomCommand = new RoutedCommand(); 
    } 
    
  2. संलग्न XAML का उपयोग कर RoutedCommand के लिए वांछित विचार:

    <Button Command="{x:Static local:MyCommands.MyCustomCommand}" /> 
    
  3. अपने विचारों में से एक है जो एक उपयुक्त ViewModel (यानी जो भी ViewModel लागू करता आदेश कार्यक्षमता) की जरूरत के लिए बाध्य है जो अपने ViewModel के कार्यान्वयन के लिए बाध्य होंगे एक कस्टम DependencyProperty बेनकाब करने के लिए:

    public partial class MainView : UserControl 
    { 
        public static readonly DependencyProperty MyCustomCommandProperty = 
         DependencyProperty.Register("MyCustomCommand", 
         typeof(ICommand), typeof(MainView), new UIPropertyMetadata(null)); 
    
        public ICommand MyCustomCommand { 
         get { return (ICommand)GetValue(MyCustomCommandProperty); } 
         set { SetValue(MyCustomCommandProperty, value); } 
        } 
    
  4. गु ई एक ही दृश्य चरण 1 से RoutedCommand को ही बाँध चाहिए XAML में:

    <UserControl.CommandBindings> 
        <CommandBinding Command="{x:Static local:MyCommands.MyCustomCommand}" 
            CanExecute="MyCustomCommand_CanExecute" 
            Executed="MyCustomCommand_Executed" 
            /> 
    </UserControl.CommandBindings> 
    

    में कोड-पीछे अपने दृश्य के लिए जुड़े ईवेंट हैंडलर्स सिर्फ ICommand निर्भरता संपत्ति चरण 3 में घोषित से प्रतिनिधि होगा :

    private void MyCustomCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         e.CanExecute = command.CanExecute(e.Parameter); 
        } 
    } 
    private void MyCustomCommand_Executed(object sender, ExecutedRoutedEventArgs e) { 
        var command = this.MyCustomCommand; 
        if (command != null) { 
         e.Handled = true; 
         command.Execute(e.Parameter); 
        } 
    } 
    
  5. अंत में, XAML में कस्टम निर्भरता संपत्ति के लिए अपने ViewModel के आदेश कार्यान्वयन (जो एक ICommand होना चाहिए) के लिए बाध्य:

    <local:MainView DataContext="{Binding MainViewModel}" 
           MyCustomCommand="{Binding CustomCommand}" /> 
    

इस दृष्टिकोण का लाभ यह है कि आपके व्यूमोडेल को केवल आईसीओएमएंड इंटरफ़ेस का एक ही कार्यान्वयन प्रदान करने की आवश्यकता है (और यह रिले कॉमांड भी हो सकता है), जबकि बिना किसी दृश्य के रूटआउट कॉमांड के माध्यम से किसी भी दृश्य को संलग्न किया जा सकता है सीधे उस ViewModel से बंधे हैं।

दुर्भाग्य से आईसीओएमएंड.कैनएक्सक्यूट चेंजेड इवेंट काम नहीं करेगा। जब आपका ViewModel CanExecute प्रॉपर्टी को रीफ्रेश करने के लिए दृश्य चाहता है तो आपको CommandManager को कॉल करना होगा। अविश्वसनीय RequerySuggested()।

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