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
好吧,MVVM只是一种模式或哲学,所以我认为你避免使用框架的愿望可能有点误导。 即使你没有使用其中一个框架,你也可以编写自己的框架来实现MVVM模式。
话虽这么说,你可能想要使用的是DelegateCommand
或其中一个类似的实现。 请参阅: http : //www.wpftutorial.net/DelegateCommand.html 。 我认为您正在寻找的重要部分是WPF按钮绑定的命令必须在视图模型中发生更改时引发CanExecuteChanged
事件,这会影响命令是否可以执行。
因此,在您的情况下,您可能希望将CanExecuteChanged
的AddPersonDelegateCommand
调用添加到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
属性。