我甚至不知道这是否是正确的标题,但无论如何。我正在从WinForms切换并尝试学习WPF和MVVM方法。
我有一个自定义类Incident
,用于存储我的团队必须响应的事件数据。我正在构建一个View,以便将该类的实例中的数据显示给用户,并允许该用户对其进行操作。需要显示多个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值的部分。请帮忙吗?
答案 0 :(得分:1)
你是对的 - 视图模型应该控制更改,文本框应该通过绑定进行更新。
在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
对象上设置它作为(“模型”对象)的视图模型的属性,并且还应该引发{ {1}}事件。否则,您的PropertyChanged
类必须实现Incident
,并且模型和视图模型类之间的界限变得不那么清晰。
答案 1 :(得分:0)
我假设您已将表单绑定到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中找到的辅助方法。有关RelayCommand的信息,请参阅Josh Smith。
其次,您需要在事件模型上实现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();
}
}
}