使用Button_Click事件使用MVVM更改文本框内容
本文关键字:文本 MVVM Button Click 事件 使用 | 更新日期: 2023-09-27 18:09:55
我甚至不知道这个标题是否合适,但无论如何。我正在从WinForms切换到尝试学习WPF和MVVM方法。
我有一个自定义类Incident
,用于存储关于我的团队必须响应的事件的数据。我正在构建一个视图,将该类实例中的数据显示给用户,并允许该用户操作它。需要显示的DateTime
数据有Start
、End
、Notification_Received
、Actions_Taken
几条。我需要有一个小按钮,将DateTime.Now
放入每个相关的TextBox
,以及改变Incident
类的当前加载实例的基础值。
我正在想办法做这件事。使用WinForms,我只是将TextBox.Text
和Incident.Start
(等)设置为DateTime.Now
都在同一个Button_Click
函数中,但我对MVVM的理解是,我不应该这样做,相反,我应该将TextBox
绑定到VM并更新VM的值。
这就是我被卡住的地方。我很确定我很擅长如何做绑定,但不是我从Button_Click
函数更改VM值的部分。请协助?
您是正确的-视图模型应该控制更改,并且文本框应该通过绑定更新。
在MVVM模式中,很少使用代码隐藏。您需要一个命令绑定,而不是Button_Click
方法:
<Button Command="{Binding SetAllDatesToNowCommand}"/>
当按钮被按下时命令将被执行。SetAllDatesToNowCommand
是一个命令处理程序-它应该是视图模型上的ICommand
属性:
public ICommand SetAllDatesToNowCommand { get; private set; }
我通常倾向于使用MVVM Light Toolkit中的RelayCommand
来创建命令处理程序,因为语法干净且非常简单。命令处理程序在视图模型的构造函数中初始化。传递给RelayCommand
的处理程序方法是您应该在所选Incident
对象上设置属性的地方:
public YourViewModel()
{
this.SetAllDatesToNowCommand =
new RelayCommand(this.ExecuteSetAllDatesToNowCommand);
}
...
public void ExecuteSetAllDatesToNowCommand()
{
this.selectedIncident.Start = DateTime.Now;
// etc.
}
如果文本框上的绑定设置正确,并且正在设置的属性正在触发适当的PropertyChanged
事件,那么当在命令执行方法中设置属性时,它们应该被更新。
然而,我建议你应该有一个Incident
的视图模型,它实现了INotifyPropertyChanged
接口。上面概述的命令将是该视图模型上的一个属性。例如,在视图模型上设置Start
属性应该设置作为视图模型的Incident
对象("模型"对象)上的属性,并且还应该引发PropertyChanged
事件。否则,您的Incident
类将不得不实现INotifyPropertyChanged
,并且模型和视图模型类之间的界限变得不那么清晰。
我假设您已经将表单绑定到ViewModel。因此你有一个属性在你的ViewModel的Start。你想要绑定一个字段到
<TextBlock Text={Binding Start}/>
或
<TextBlock Text={Binding Incident.Start}/>
取决于你如何暴露事件。要更新Start,你必须做两件事。在按钮上使用命令
<Button Command="{Binding TestCommand}">Test</Button>
在ViewModel中定义命令。
private RelayCommand _testCommand;
public RelayCommand TestCommand
{
get
{
return _testCommand ?? (_testCommand = new RelayCommand(TestUpdate, CanRunTest));
}
set
{
if (_testCommand == value) return;
_testCommand = value;
}
}
public bool CanRunTest()
{
return some boolean test that defines if the command can run now;
}
private void TestUpdate()
{
Incident.Start = DateTime.Now;
}
RelayCommand是一个辅助方法,你可以在MVVMLight中找到。也可以参见Josh Smith获取RelayCommand的信息。
第二,你需要在事件模型上实现INotifyPropertyChanged或查找ObservableObject并使你的Start属性看起来像这样。
public class Incident : ObservableObject
{
private ObservableCollection<WordLetter> _start;
public virtual ObservableCollection<WordLetter> Start
{
get { return _start; }
set
{
if (value == _start) return;
_start = value;
NotifyPropertyChanged();
}
}
}