WPF简单指挥示例

我尽量不发布这样的问题,但我一直在努力寻找答案或类似的例子。 我认为这是一个我想设置的非常简单的例子。 基本上我想使用命令将项目从文本框添加到列表框。 我想通过CanExecute确保文本框中有一些内容,我想确保它不在列表中。

我知道这看起来似乎过于复杂,但它在我一直在努力的某些方面受到打击。

简单的界面

     Name       

我有一个人类

 class Person { public string Name { get; set; } } 

我有这个的唯一原因是Add需要创建一个新对象,所以比简单的字符串稍微复杂一些。

然后是一个基本的视图模型

 class MainViewModel : INotifyPropertyChanged { public MainViewModel() { People = new ObservableCollection(); People.Add( new Person {Name = "jimmy"}); } public ObservableCollection People { get; set; } #region Default INotifyPropertyChanged implimentation public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } #endregion } 

所以问题是,如果名称已经存在或名称字段为空,我将如何实现命令以便它使用CanExecute禁用“添加”按钮。

然后同样的删除交易,只有在列表中选择了名称时才启用。

我想尽可能地将它作为MVVM的赞美。

我已经看到你可以执行Button.CommandBindings附加属性来注入你想要为每个方法使用的方法,但这似乎并不完全是MVVM高兴的。

此外,我想避免使用框架(Prism / Caliburn.Micro),因为这主要是出于教育原因。

此外,任何参考资料将不胜感激。 我已经阅读了很多博客等,但在实现一个完整, 简单的例子之前,我总觉得他们偏离了。

如果名称已存在或名称字段为空,我将如何实现命令以便它使用CanExecute禁用“添加”按钮

我将展示如何进行添加,删除类似,我留下让你弄明白。 首先,我将使用AddPerson命令使用按钮显示xaml更改:

   

我们已将当前编辑的文本绑定到名为CurrentPerson的视图模型上的新属性。 这样做是因为我们想要访问该人输入的内容,但我们还需要在用户输入时更新绑定。 要完成更新,我们通过将UpdateSourceTrigger属性设置为PropertyChanged来指定绑定更新。 否则我们的CurrentPerson字符串和最终命令Can操作只会在编辑文本框失去焦点时触发。

ViewModel viewmodel将订阅AddPerson命令。 执行该操作将添加用户,但也检查一个can方法,该方法返回一个布尔值是否启用该按钮。 当CurrentPerson属性发生变化时,我们最终RaiseCanExecuteChanged在命令类上调用RaiseCanExecuteChanged以使按钮检查can方法时, can

此VM缩写为示例并基于您的完整VM

 public OperationCommand AddPerson { get; set; } public string _currentPerson; public MainViewModel() { People = new ObservableCollection(); People.Add(new Person { Name = "jimmy" }); // First Lamda is where we execute the command to add, // The second lamda is the `Can` method to enable the button. AddPerson = new OperationCommand((o) => People.Add(new Person { Name = CurrentPerson }), (o) => (!string.IsNullOrWhiteSpace(CurrentPerson) && !People.Any(per => per.Name == CurrentPerson))); // When the edit box text changes force a `Can` check. this.PropertyChanged += MainViewModel_PropertyChanged ; } void MainViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "CurrentPerson") AddPerson.RaiseCanExecuteChanged(); } 

最后这里是使用的命令类,它基于我的博客文章Xaml:ViewModel主页实例化和更容易绑定的加载策略。 :

 public class OperationCommand : ICommand { #region Variables Func canExecute; Action executeAction; public event EventHandler CanExecuteChanged; #endregion #region Properties #endregion #region Construction/Initialization public OperationCommand(Action executeAction) : this(executeAction, null) { } public OperationCommand(Action executeAction, Func canExecute) { if (executeAction == null) { throw new ArgumentNullException("Execute Action was null for ICommanding Operation."); } this.executeAction = executeAction; this.canExecute = canExecute; } #endregion #region Methods public bool CanExecute(object parameter) { bool result = true; Func canExecuteHandler = this.canExecute; if (canExecuteHandler != null) { result = canExecuteHandler(parameter); } return result; } public void RaiseCanExecuteChanged() { EventHandler handler = this.CanExecuteChanged; if (handler != null) { handler(this, new EventArgs()); } } public void Execute(object parameter) { this.executeAction(parameter); } #endregion } 

好吧,MVVM只是一种模式或哲学,所以我认为你避免使用框架的愿望可能有点误导。 即使你没有使用其中一个框架,你也可以编写自己的框架来实现MVVM模式。

话虽这么说,你可能想要使用的是DelegateCommand或其中一个类似的实现。 请参阅: http : //www.wpftutorial.net/DelegateCommand.html 。 我认为您正在寻找的重要部分是WPF按钮绑定的命令必须在视图模型中发生更改时引发CanExecuteChanged事件,这会影响命令是否可以执行。

因此,在您的情况下,您可能希望将CanExecuteChangedAddPersonDelegateCommand调用添加到CanExecuteChanged方法(可能通过已更改的属性的名称进行过滤)。 这告诉命令绑定命令的任何东西,然后你可以在CanExecute中使用你的逻辑来确定是否已经存在输入名称的人。

所以要添加一些示例代码,它可能看起来像这样:

 class MainViewModel : INotifyPropertyChanged { public MainViewModel() { People = new ObservableCollection(); People.Add( new Person {Name = "jimmy"}); AddPersonDelegateCommand = new DelegateCommand(AddPerson, CanAddPerson); } // Your existing code here protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { if(propertyName == "NewNameTextBox") AddPersonDelegateCommand.RaiseCanExecuteChanged(); PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } public DelegateCommand AddPersonDelegateCommand { get; set; } public void AddPerson() { // Code to add a person to the collection } public bool CanAddPerson() { return !People.Any(p=>p.Name == NewNameTextBox); } public string NewNameTextBox { get { return _newNameTextBox; } set { _newNameTextBox = value; OnPropertyChanged(); } } } 

*注意:在此示例中, 需要绑定到视图模型上的NewNameTextBox属性。