2010-05-19 60 views
3

我正在使用MVVM模式。我有一個TextBox和按鈕 - 綁定和命令

  1. 文本框,其文本屬性綁定到視圖模型的(VM支持INotifyProperyChange)Text屬性
  2. 按鈕,其命令綁定到虛擬機的ICommand的屬性類型

你可能會認爲這是一個SearchTextBox和SearchButton

我面臨的問題是,當我在SearchTextBox中輸入文本並單擊SearchButton時,只有SearchTextBox綁定set屬性實現被調用,但(注意:ICommand CanExecute handler總是返回True)

它工作正常,如果我使用TAB鍵標籤出SearchTextBox或使用鼠標從SearchTextBox移動焦點,然後單擊SearchButton。這意味着做兩個單獨的行動來分別觸發兩個事件。理想情況下,單擊SearchButton應導致SearchTextBox鬆散焦點,因此調用Set屬性,並單擊Search按鈕轉換爲命令執行。

代碼是如下

XAML:

<TextBox Text="{Binding Path=SearchText,Mode=TwoWay}"/> 

<Button Content="Search" Width="100" Command="{Binding MySearchCommand}"/> 

C#:

public String _SearchText; 
public String SearchText 
{ 
    get { return _SearchText; } 
    set 
    { 
    _SearchText = value; 
    OnPropertyChanged("SearchText"); 
    } 
} 

ICommand實現與沒有花哨的代碼和CanExecute處理標準implemenetation總是返回true

+0

你怎麼說當你的CanExecute運行你的命令不執行?你可以在這裏發佈實現嗎?(你的Execute方法) – Amsakanna 2010-05-19 12:13:12

+1

我認爲字節意味着CanExecute沒有運行,但是被定義爲總是返回true。 – 2010-05-19 12:40:57

+1

只有一些愚蠢的錯誤,請張貼您的代碼:) – 2010-05-19 12:41:30

回答

0

嘗試隔離issu e通過編寫一個複製問題的小型測試項目,如果您可以重新報告,請發佈代碼。通常,當您在主項目之外再現問題時,問題和解決方案會變得很明顯。

+0

這就是我現在正在做的! – byte 2010-05-19 13:47:48

0

我創建了一個示例應用程序來重現此問題。

我放置了斷點並在SearchText中添加了一個Debug.Writeline - 設置屬性和MySearchCommandExecute方法。

當設置斷點時,只有SearchText - Set屬性被調用。我觀察到,如果我從SearchText中移除斷點 - Set屬性,則屬性和命令都會正確執行。看起來像VS 2008的一些問題,但我可能是錯的。

相關的示例代碼如下

class SearchViewModel : ViewModelBase 
    { 
     public SearchViewModel() 
     { 

     } 

     public String _SearchText; 
     public String SearchText 
     { 
      get { return _SearchText; } 
      set 
      { 
       System.Diagnostics.Debug.WriteLine("Set Membership called"); 

       OnPropertyChanged("SearchText"); 
      } 
     } 

     #region Commands 
     RelayCommand _SearchCommand; 

     public ICommand SearchCommand 
     { 
      get 
      { 
       if (_SearchCommand == null) 
       { 
        _SearchCommand = new RelayCommand(param => this.MySearchCommandExecute(), param => this.MySearchCommandCanExecute); 
       } 
       return _SearchCommand; 
      } 
     } 

     public void MySearchCommandExecute() 
     { 
      System.Diagnostics.Debug.WriteLine("MySearchCommandExecute called"); 

      // Do Search 
     } 

     public bool MySearchCommandCanExecute 
     { 
      get 
      { 
       return true; 
      } 
     } 

     #endregion 
    } 

SearchView.xaml

<UserControl x:Class="WpfApplication2.SearchView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <StackPanel> 
     <StackPanel Orientation="Vertical" HorizontalAlignment="Left" Margin="4"> 
      <Label Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Content="SearchText"/> 
      <TextBox Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Text="{Binding Path=SearchText}"/> 
     </StackPanel> 
     <Button HorizontalAlignment="Left" Content="Search" Width="100" Command="{Binding SearchCommand}" Margin="8"/> 
    </StackPanel> 
</UserControl> 

RelayCommand.cs

// Reference: MSDN sample 
    class RelayCommand : ICommand 
    { 
     readonly Action<object> _execute; 
     readonly Predicate<object> _canExecute; 

     public RelayCommand(Action<object> execute) 
      : this(execute, null) 
     { 
     } 

     public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) 
       throw new ArgumentNullException("relaycommand execute"); 

      _execute = execute; 
      _canExecute = canExecute; 
     } 

     [DebuggerStepThrough] 
     public bool CanExecute(object parameter) 
     { 
      return _canExecute == null ? true : _canExecute(parameter); 
     } 

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

     public void Execute(object parameter) 
     { 
      _execute(parameter); 
     } 
    } 
0

字節,

對不起,我遲到響應,但我希望我反正無論如何都會變得方便。最近我很忙,所以我無法調試你的代碼(當我有更多的時間時,我會盡量做到這一點),但請嘗試下面粘貼的示例代碼(它完全適用於我)。你可以看到它非常簡單。我用你的xaml,但對於窗口:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     this.DataContext = new TempViewModel(); 
    } 
} 

public class TempViewModel : INotifyPropertyChanged 
{ 
    private String _searchText; 
    private ICommand _searchCommand; 

    #region Commands 

    protected class Search : ICommand 
    { 
     private TempViewModel _viewModel; 

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

     public event EventHandler CanExecuteChanged 
     { 
      add { } 
      remove { } 
     } 

     public void Execute(object parameter) 
     { 
      //MessageBox in VM is just for demonstration 
      MessageBox.Show("command executed with search string: " + this._viewModel._searchText); 
     } 

     public Search(TempViewModel viewModel) 
     { 
      this._viewModel = viewModel; 
     } 
    } 

    #endregion //Commands 

    #region INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(String propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion //INotifyPropertyChanged 

    #region Public properties 

    public String SearchText 
    { 
     get 
     { 
      return this._searchText; 
     } 
     set 
     { 
      this._searchText = value; 
      OnPropertyChanged("SearchText"); 
     } 
    } 

    public ICommand SearchCommand 
    { 
     get 
     { 
      return this._searchCommand; 
     } 
     set 
     { 
      this._searchCommand = value; 
      OnPropertyChanged("SearchCommand"); 
     } 
    } 

    #endregion //Public properties 

    public TempViewModel() 
    { 
     this.SearchCommand = new Search(this); 
     this.SearchText = "Sample string"; 
    } 
} 

請隨時問,如果您有任何其他問題。

編輯:啊,對不起,但我改變Command="{Binding SearchCommand}"Command="{Binding Path=SearchCommand}"