我正在使用MVVM模式。我有一个
您可能会将此视为SearchTextBox和SearchButton
我面临的问题是,当我在SearchTextBox中输入文本并单击SearchButton时,只会调用SearchTextBox绑定的set
属性实现,但SearchButton点击的Command
永远不会执行(注意: ICommand CanExecute handler
始终返回True)
如果我使用TAB键跳出SearchTextBox或使用鼠标将焦点从SearchTextBox移开,然后单击SearchButton,它可以正常工作。这意味着要做两个单独的动作来单独触发这两个事件。理想情况下,单击SearchButton会导致SearchTextBox松散焦点,从而调用Set
属性,单击“搜索”按钮会转换为命令执行。
代码如下
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
处理程序总是返回True
答案 0 :(得分:0)
尝试通过编写一个重现问题的小型测试项目来隔离问题,如果您可以重新发布,请发布代码。通常当你在主项目之外重新解决问题时,问题和解决方案就变得很明显了。
答案 1 :(得分: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);
}
}
答案 2 :(得分:0)
字节,
对不起我迟到的回复,但我希望无论如何都会变得方便。我最近很忙,所以我无法调试你的代码(当我有更多时间时我会尝试这样做),但请尝试下面粘贴的示例代码(它对我来说非常适合)。你可以看到它非常简单。我使用了你的xaml,但是对于Window:
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}"