WPF

2012-12-12 23 views
12

में कमांड को कैसे बाध्य करें कभी-कभी हमने कई बार जटिल तरीकों का उपयोग किया, हम कार्य करने के सबसे सरल तरीकों को भूल गए।WPF

मुझे पता है कि कमांड बाध्यकारी कैसे करें, लेकिन मैं हमेशा एक ही दृष्टिकोण का उपयोग करता हूं।

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

इस कोड है कि मैं बाध्यकारी

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this;    
     testCommand = new MeCommand(processor); 
    } 

    ICommand testCommand; 

    public ICommand test 
    { 
     get { return testCommand; } 
    } 
    public void processor() 
    { 
     MessageBox.Show("hello world"); 
    } 
} 

public class MeCommand : ICommand 
{ 
    public delegate void ExecuteMethod(); 
    private ExecuteMethod meth; 
    public MeCommand(ExecuteMethod exec) 
    { 
     meth = exec; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return false; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     meth(); 
    } 
} 

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

उत्तर

13

Prism पहले से ही Microsoft.Practices.Prism.Commands.DelegateCommand

प्रदान की मुझे यकीन है कि नहीं कर रहा हूँ यह 3 पार्टी के रूप में माना है। कम से कम यह आधिकारिक है और एमएसडीएन पर दस्तावेज है।

कुछ देशी बिल्ड-इन आदेशों की प्रतिलिपि, पेस्ट आईसीओएमएंड इंटरफ़ेस लागू करता है। IMHO इसे ओपन (विस्तार के लिए)/बंद (परिवर्तनों के लिए) सिद्धांत का पालन करता है। ताकि हम अपने आदेश को कार्यान्वित कर सकें।


अद्यतन

के रूप में WPF कमांडिंग प्रलेखित here, एक अंश ...

WPF पूर्वनिर्धारित आदेशों का एक सेट प्रदान करता है। जैसे कट, ब्राउजबैक और ब्राउज़ करें फॉरवर्ड, प्ले, स्टॉप, और पॉज़।

यदि कमांड लाइब्रेरी कक्षाओं में कमांड आपकी आवश्यकताओं को पूरा नहीं करते हैं, तो तो आप अपना खुद का आदेश बना सकते हैं। कस्टम कमांड बनाने के दो तरीके हैं। पहला ग्राउंड अप से शुरू करना है और आईसीओएमएंड इंटरफ़ेस लागू करना है। दूसरी तरफ, और अधिक सामान्य दृष्टिकोण, RoutedCommand या RoutedUICommand बनाना है।

मैंने शुरुआत में रूटेड कॉमांड मॉडल की कोशिश की है और आईसीओएमएंड लागू करने के साथ समाप्त हो गया है।

नमूना XAML बाइंडिंग

<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}" 
        Executed="ExecutedCustomCommand" 
        CanExecute="CanExecuteCustomCommand" /> 

RoutedCommand RoutedEvent से अलग नहीं है। यह एक बेहतर बटन के 'क्लिकेड' ईवेंट हैंडलर जैसा लगता है। यह उद्देश्य प्रदान करता है: ऐप लॉजिक को व्यू से अलग करने के लिए, लेकिन कुछ अनुलग्नक निर्भरता प्रॉपर्टी या कोड-बैक की आवश्यकता होती है।

व्यक्तिगत रूप से मैं अपने आईसीओएमएंड को लागू करने के साथ व्यक्तिगत रूप से अधिक आरामदायक महसूस करता हूं।

+1

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

+1

एकमात्र ऐसा व्यक्ति होने के लिए उपरोक्त जो वास्तव में प्रश्न पढ़ता है। – psycho

+0

@psycho एकमात्र ऐसा व्यक्ति होने के लिए रचनात्मक टिप्पणी जो मेरे दर्द को समझती है। :-) – MegaMind

0

ठीक है, आपके पास लगभग है। बस सुनिश्चित करें कि CanExecute() सत्य वापस आ जाएगा, अन्यथा आपका कोड निष्पादित नहीं किया जाएगा। (मुझे लगता है कि यह वास्तव में होगा, लेकिन फिर भी)।यह भी सुनिश्चित करें कि यहाँ के

public ICommand test 
    { 
     get { return testCommand; } 
     set { testCOmmand = value; NotifyPropertyChanged("test"); } 
    } 

करने के लिए "NotifyPropertyChanged ('yourCommand')" जोड़ने बनाते हैं।

आप वैकल्पिक रूप से परीक्षण = नया MeCOmmand() कर सकते हैं; डेटाकॉन्टेक्स्ट = यह;

+0

इस आदेश के निष्पादन पर मैं जिस विधि को निष्पादित करना चाहता हूं वह कहां है? और वैकल्पिक रूप से आप मेकॉमैंड क्लास का उपयोग करने के लिए कह रहे हैं, लेकिन जैसा कि मैंने उल्लेख किया है, मैं किसी भी कस्टम क्लास का उपयोग नहीं करना चाहता हूं। – MegaMind

+0

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

+0

आप डाउनवोट सिर्फ इसलिए कि आपने अपने प्रश्न में खुद को स्पष्ट नहीं किया है। अच्छी शैली नहीं है। –

1

क्या आप वी.एस. में कोड चलने के बिना कर से परखने के बाद, आपकी समस्या को आप कॉल कि InitializeComponent (XAML प्रस्तुत करना), तो किसी भी कीमत अपने test संपत्ति में किया जा रहा है और अंत में एक निजी सदस्य सेट बिना DataContext सेट है। यूआई को यह नोटिस करना चाहिए कि आपका कमान अब शून्य नहीं है (जो संपत्ति में पाया गया अंतिम मूल्य था)?

क्यों इतने तरह lazily कमान instanciate नहीं:

public ICommand test 
{ 
    get 
    { 
     if(testCommand== null) 
     { 
     testCommand= new MeCommand(processor); 
     } 
     return testCommand; 
    } 
} 

यह इसी तरह से वहाँ के रूप में जल्दी ही हो जाएगा के रूप में यह आवश्यक है और आप अधिसूचना बदलें (जब तक आप रनटाइम पर बाद में उस आदेश को बदलने) की जरूरत नहीं है।

1) CanExecute() झूठे रिटर्न: सिर्फ सच वापसी करने या अपने व्यापार के मामले के अनुसार मूल्यांकन

वैसे, कुछ धब्बे जहां भावना कोई कोड कमान बाइंडिंग परिदृश्य में क्रियान्वित किया जा रहा है मिलता है ।

2) CanExecute परिवर्तन की शर्तें, ताकि यह सच हो जाए, लेकिन इसे कॉल नहीं किया जाता है: आप कमांड मैनेजर क्लास के साथ अपने कमांड को हुक कर सकते हैं, here देखें। सुनिश्चित करें कि 1) इसे आजमाने से पहले हल किया गया है। यह सुनिश्चित करता है कि आपके UI को CanExecute बहुत बार आवश्यकता होगी, और यदि यह अभी भी पर्याप्त नहीं है, तो विधि CommandManager.InvalidateRequerySuggested() स्पष्ट रूप से कॉल करें।

3) आपका बाध्यकारी गलत है। इसलिए जैसे बाध्यकारी कोड बदलें:

Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}" 

यह आपके उत्पादन खिड़की जब भी बंधन का मूल्य खींच लिया या धकेल दिया जाता है स्पैम होगा। शब्द "अंतिम मूल्य का उपयोग" के लिए देखें। यदि यह शून्य है, तो आपका कमान वह नहीं है जहां यह होना चाहिए (अभी तक)।

+0

मेरा बाध्यकारी ठीक है, इसके बारे में कोई समस्या नहीं है। मैं सिर्फ यह जानना चाहता हूं कि किसी अन्य वर्ग में आईसीओएमएंड लागू किए बिना कमांड को कैसे बांधें और फिर उस वर्ग का उपयोग करें। मेरे मामले में इसके मेकॉमैंड। – MegaMind

+2

कमांड बाइंडिंग केवल आईसीओएमएंड के कार्यान्वयन के साथ काम करता है। यह डब्ल्यूपीएफ कन्वेंशन है, मदद नहीं की जा सकती है। शायद आप रिलेकॉमैंड जैसे कुछ का उपयोग करने के बारे में सोचना चाहेंगे [यहां] (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)। इसकी जांच - पड़ताल करें। –

+2

ईमानदारी से, हम सभी को क्यों कम करें? सोचो कि यह समुदाय की मदद करता है? –

2

यदि आप नई कक्षा नहीं बनाना चाहते हैं तो कृपया रूटेड कमांड का उपयोग करें। यहाँ एक छोटा स्निपेट है। मैं सहेजें के रूप में एक कराई आदेश बनाया है और यह बाँध खिड़की के बंधन को आदेश, button.and देखा से आदेश को बढ़ाने के लिए! ..... मुझे आशा है कि यह आप

public partial class Window1 : Window 
{ 
    public static readonly RoutedCommand Foo = new RoutedCommand(); 

    public Window1() 
    { 
     InitializeComponent(); 
    } 

    void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     // The Window gets to determine if the Foo 
     // command can execute at this time. 
     e.CanExecute = true; 
    } 

    void Foo_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     // The Window executes the command logic when the user wants to Foo. 
     MessageBox.Show("The Window is Fooing..."); 
    } 
} 

<Window.CommandBindings> 
<CommandBinding 
    Command="{x:Static local:Window1.Foo}" 
    CanExecute="Foo_CanExecute" 
    Executed="Foo_Executed" 
    /> 

मैं मदद मिल सकती है उम्मीद है कि मैं आपकी समस्या को अच्छी तरह समझ गया हूं।

पीएस: कमांड डिज़ाइन पैटर्न की आवश्यकता निष्पादन के तर्क को कम करने और आदेश के आवेदक को कम करने के लिए है। इसलिए कमांड क्लास तर्क को समाहित करने का एक तरीका है।

3

मैं एमवीवीएम लाइट फ्रेमवर्क का उपयोग करता हूं जो रिलेकॉमैंड के साथ आता है।XAML में

ICommand ClickMeCommand {get;set;} 
private void InitCommands() 
{ 
    ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true); 
    //or 
    ClickMeCommand = new RelayCommand(ClickMeEvent); 
} 
public void ClickMeEvent() 
{ 
    HasBeenClicked=true; 
} 

तुम सिर्फ का उपयोग सामान्य बंधन: - -:

आप अपने दृश्य मॉडल के लिए एक ICommand प्रॉपर्टी जोड़ते हैं, तो यह करने के लिए एक relaycommand आवंटित

<Button Content='Push me' Command='{Binding ClickMeCommand}' /> 
0

WPF विंडो में एक कीबोर्ड शॉर्टकट को जोड़ने के लिए कन्स्ट्रक्टर, बस एक प्रतिनिधि के साथ बाध्यकारी जोड़ें, और इसे एक प्रमुख इशारा के साथ संबद्ध करें।

public YourWindow() //your constructor 
{ 
    ... 
    //bind keyboard command shortcuts 
    InputBindings.Add(new KeyBinding(//add a new key-binding, bind it to your command object which takes a delegate 
     new WindowCommand(this) 
     { 
     ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate 
     }, new KeyGesture(Key.P, ModifierKeys.Control))); 
    ... 
} 

एक साधारण विंडो कॉमांड क्लास बनाएं जो किसी भी विधि सेट को बंद करने के लिए निष्पादन प्रतिनिधि लेता है।

public class WindowCommand : ICommand 
{ 
    private MainWindow _window; 
    public Action ExecuteDelegate { get; set; } 

    public WindowCommand(MainWindow window) 
    { 
     _window = window; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     if (ExecuteDelegate != null) 
     { 
      ExecuteDelegate(); 
     } 
     else 
     { 
      throw new InvalidOperationException(); 
     } 
    } 
}