2013-02-22 13 views
8

मेरे पास एक कमांड के साथ व्यूमोडेल से जुड़े बटन के साथ एक सरल-जैसी खिड़की हो सकती है।आदेश अक्षम नहीं होता है जब आदेश CanExecute गलत है

मुझे उम्मीद है कि बटन को अक्षम करने की उम्मीद है यदि MyCommand.CanExecute() गलत है। लेकिन ऐसा लगता है कि जब पहली बार खिड़की खींची जाती है तो WPF केवल IsEnabled गुण सेट करेगा। कोई भी आगामी कार्रवाई बटन की दृश्य स्थिति को प्रभावित नहीं करती है। मैं प्रिज्म से एक प्रतिनिधिमंडल का उपयोग कर रहा हूँ।

मेरे दृश्य:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Button Content="Click Here" Command="{Binding MyCommand}" Width="100" Height="50"/> 
</Grid> 

और मेरे ViewModel: समय की

public class MyVM : NotificationObject 
{ 
    public MyVM() 
    { 
     _myCommand = new DelegateCommand(DoStuff, CanDoStuff); 
    } 

    private void DoStuff() 
    { 
     Console.WriteLine("Command Executed"); 
     _myCommand.RaiseCanExecuteChanged(); 
    } 

    private bool CanDoStuff() 
    { 
     var result = DateTime.Now.Second % 2 == 0; 
     Console.WriteLine("CanExecute is {0}", result); 
     return result; 
    } 

    private DelegateCommand _myCommand; 

    public ICommand MyCommand 
    { 
     get 
     { 
      return _myCommand; 
     } 
    } 
} 

50%, जब मेरे आवेदन लोड, बटन ठीक से अक्षम है। हालांकि, यदि विंडो लोड होने पर यह सक्षम होता है, और मैं कमांड निष्पादित करने के लिए बटन क्लिक करता हूं, तो मुझे बटन के अक्षम होने के 50% समय की उम्मीद है, लेकिन यह कभी नहीं करता है। आदेश निष्पादित नहीं होता है, लेकिन मैं अभी भी बटन पर क्लिक कर सकता हूं। मैं समझने के लिए WPF कैसे प्राप्त करूं कि CanExecute() गलत होने पर बटन अक्षम होना चाहिए?

+0

पहली बात तुम क्या करने की जरूरत है डेटा बाइंडिंग के लिए डीबग संदेश बारी है: http://i.stack.imgur.com/MF8i5.png इसके बाद, आउटपुट विंडो को दोबारा चलाएं और जांचें और देखें कि क्या त्रुटियां हैं। यदि कोई भी आपके आदेश बाध्यकारी से संबंधित नहीं है, तो 'RaiseCanExecuteChanged()' का आपका कार्यान्वयन गलत/छोटी है। – Will

+0

आपकी CanDOStuff विधि वास्तव में अजीब है! यह आपके बटन को अक्षम कर सकता है, लेकिन अगले सेकंड में आपका आदेश निष्पादित हो सकता है, लेकिन बटन अक्षम है ... वास्तव में wierd। लेकिन आपको [CommandManager.InvalidateRequerySuggested()] (http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.invalidaterequerysuggested.aspx) कॉल करना चाहिए यदि आपका CanExecute बदला जा सकता है और UI नहीं है अपडेट किया गया क्योंकि CanExecuteChanged नहीं उठाया गया था। –

+0

@ विकटर मुझे पता है कि यह वास्तव में अजीब है, यह एक मूर्ख उदाहरण होना चाहिए जो यादृच्छिक रूप से सच/गलत लौटाता है। CommandManager.InvalidateRequery सुझाया गया कोई प्रभाव नहीं है। –

उत्तर

6

मुझे लगता है कि आप प्रिज्म और उसके NotificationObject और DelegateCommand का उपयोग कर रहे हैं, इसलिए हमें उम्मीद करनी चाहिए कि RaiseCanExecuteChanged() में कोई बग न हो।

हालांकि, व्यवहार के लिए कारण यह है कि प्रिज्म के RaiseCanExecuteChanged तुल्यकालिक संचालित है, इसलिए हम अभी भी ICommand.Execute() के कार्यान्वयन के अंदर कर रहे हैं और परिणाम तो ध्यान नहीं दिया जा करने के लिए प्रकट होता है, जबकि CanDoStuff() कहा जाता है।

यदि आप अपने आदेश के साथ एक और बटन बनाते हैं और उस आदेश/बटन से _myCommand.RaiseCanExecuteChanged() पर कॉल करते हैं, तो पहले बटन को आप सक्षम/अक्षम कर देंगे।

या, यदि आप MVVM प्रकाश के साथ एक ही बात की कोशिश और RelayCommand क्योंकि MVVM लाइट के RaiseCanExecuteChanged कॉल CommandManager.InvalidateRequerySuggested() जो CanDoStuff को कॉलबैक का आह्वान एसिंक्रोनस रूप Dispatcher.CurrentDispatcher.BeginInvoke का उपयोग कर, व्यवहार आप प्रिज्म के कार्यान्वयन के साथ देख रहे हैं से बचने के लिए अपने कोड काम करेंगे।

+0

धन्यवाद। मैंने आपके दोनों सुझावों की कोशिश की, और वे जगह पर हैं। प्रिज्म की दुर्भाग्यपूर्ण सीमा की तरह लगता है। –

0

आप इस कोशिश कर सकते हैं (Microsoft.Practices.Prism.dll आवश्यक है)

public class ViewModel 
{ 
    public DelegateCommand ExportCommand { get; } 

    public ViewModel() 
    { 
     ExportCommand = new DelegateCommand(Export, CanDoExptor); 
    } 

    private void Export() 
    { 
     //logic 
    } 

    private bool _isCanDoExportChecked; 

    public bool IsCanDoExportChecked 
    { 
     get { return _isCanDoExportChecked; } 
     set 
     { 
      if (_isCanDoExportChecked == value) return; 

      _isCanDoExportChecked = value; 
      ExportCommand.RaiseCanExecuteChanged(); 
     } 
    } 

    private bool CanDoExptor() 
    { 
     return IsCanDoExportChecked; 
    } 
} 
संबंधित मुद्दे