使用Button_Click事件使用MVVM更改文本框内容

本文关键字:文本 MVVM Button Click 事件 使用 | 更新日期: 2023-09-27 18:09:55

我甚至不知道这个标题是否合适,但无论如何。我正在从WinForms切换到尝试学习WPF和MVVM方法。

我有一个自定义类Incident,用于存储关于我的团队必须响应的事件的数据。我正在构建一个视图,将该类实例中的数据显示给用户,并允许该用户操作它。需要显示的DateTime数据有StartEndNotification_ReceivedActions_Taken几条。我需要有一个小按钮,将DateTime.Now放入每个相关的TextBox,以及改变Incident类的当前加载实例的基础值。

我正在想办法做这件事。使用WinForms,我只是将TextBox.TextIncident.Start(等)设置为DateTime.Now都在同一个Button_Click函数中,但我对MVVM的理解是,我不应该这样做,相反,我应该将TextBox绑定到VM并更新VM的值。

这就是我被卡住的地方。我很确定我很擅长如何做绑定,但不是我从Button_Click函数更改VM值的部分。请协助?

使用Button_Click事件使用MVVM更改文本框内容

您是正确的-视图模型应该控制更改,并且文本框应该通过绑定更新。

在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();
        }
    }
}