2010-05-19 144 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}"