Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用按钮单击事件使用MVVM更改文本框内容_C#_Wpf_Mvvm - Fatal编程技术网

C# 使用按钮单击事件使用MVVM更改文本框内容

C# 使用按钮单击事件使用MVVM更改文本框内容,c#,wpf,mvvm,C#,Wpf,Mvvm,我甚至不知道这个标题是否合适,但无论如何。我正在从WinForms转换过来,尝试学习WPF和MVVM方法 我有一个自定义类,事件,用于存储我的团队必须响应的关于发生的事件的数据。我正在构建一个视图,以便向用户显示该类实例中的数据,并允许该用户对其进行操作。需要显示几段日期时间数据-开始,结束,收到的通知,采取的行动。我需要有一个小按钮,可以将DateTime.Now放入每个关联的TextBox,并更改事件类当前加载实例的基础值 我在想怎么做。使用WinForms,我只需将TextBox.Text

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

我有一个自定义类,
事件
,用于存储我的团队必须响应的关于发生的事件的数据。我正在构建一个视图,以便向用户显示该类实例中的数据,并允许该用户对其进行操作。需要显示几段
日期时间
数据-
开始
结束
收到的通知
采取的行动
。我需要有一个小按钮,可以将
DateTime.Now
放入每个关联的
TextBox
,并更改
事件
类当前加载实例的基础值

我在想怎么做。使用WinForms,我只需将
TextBox.Text
Incident.Start
(etc)设置为
DateTime。现在
都在相同的
按钮中单击
函数,但我对MVVM的理解是我不应该这样做,而是应该将
TextBox
绑定到VM并更新VM的值


这就是我被困的地方。我很确定我在如何绑定方面做得很好,但在我从
按钮单击
函数更改VM值的部分就不行了。请协助?

我想您已经将表单绑定到ViewModel。因此,在Start的ViewModel中有一个属性。要将字段绑定到该字段吗

<TextBlock Text={Binding Start}/>
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();
        }
    }
}
公共类事件:可观察对象
{
私人可观察收集(u start);;
公共虚拟可观测集合启动
{
获取{return\u start;}
设置
{
if(value==\u start)返回;
_开始=值;
NotifyPropertyChanged();
}
}
}

你是对的-视图模型应该控制更改,文本框应该通过绑定更新

在MVVM模式中,很少使用代码隐藏。您需要的是命令绑定,而不是单击按钮
方法:

<Button Command="{Binding SetAllDatesToNowCommand}"/>
我通常倾向于使用中的
RelayCommand
来创建命令处理程序,因为语法干净且非常简单。命令处理程序在视图模型的构造函数中初始化。传递给
RelayCommand
的处理程序方法是您应该在其中设置所选
事件
对象的属性:

public YourViewModel()
{
    this.SetAllDatesToNowCommand =
        new RelayCommand(this.ExecuteSetAllDatesToNowCommand);
}

...

public void ExecuteSetAllDatesToNowCommand()
{
    this.selectedIncident.Start = DateTime.Now;
    // etc.
}
如果文本框上的绑定已正确设置,并且正在设置的属性正在触发相应的
PropertyChanged
事件,则在命令执行方法中设置属性时应更新这些属性


但是,我建议您应该为
Incident
创建一个视图模型,它实现了
INotifyPropertyChanged
接口。上面概述的命令将是该视图模型上的属性。例如,设置该视图模型上的
Start
属性应设置它作为视图模型的
Incident
对象(“模型”对象)上的属性,并且还应引发
PropertyChanged
事件。否则,您的
事件
类将必须实现
INotifyPropertyChanged
,模型和视图模型类之间的界限变得不那么清晰。

如果不使用MVVM Light Toolkit中的此
RelayCommand
,我该怎么做?我使用的是VS Express 2012,没有下载。另外,请记住,我对MVVM/WPF完全陌生,要完成一件事似乎需要大量的代码,在WinForms中需要两行代码才能完成,而且不需要遵循MVVM。所有这些额外的努力有什么好处?我很难看到它。您可以从NuGet将MVVM Light Toolkit添加到您的解决方案中-右键单击您的解决方案并选择“为解决方案管理NuGet软件包”。否则,您可以自己编写。它看起来像是更多的代码,但有一定的优势。一些示例:视图模型是可测试的,与代码隐藏不同。这本身就是一个巨大的好处。将文本框绑定到视图模型属性意味着您可以从任何位置更改属性的值,绑定到该属性的任何内容都将自动更新。在“代码隐藏”中,您必须手动进行大量布线。只需设置正确的绑定,命令就可以自动路由到不同的视图模型。您所说的“可测试”是什么意思?我觉得你的意思和你的实际意思不一样。
public class Incident : ObservableObject
{
    private ObservableCollection<WordLetter> _start;
    public virtual ObservableCollection<WordLetter> Start
    {
        get { return _start; }
        set
        {
            if (value == _start) return;
            _start = value;
            NotifyPropertyChanged();
        }
    }
}
<Button Command="{Binding SetAllDatesToNowCommand}"/>
public ICommand SetAllDatesToNowCommand { get; private set; }
public YourViewModel()
{
    this.SetAllDatesToNowCommand =
        new RelayCommand(this.ExecuteSetAllDatesToNowCommand);
}

...

public void ExecuteSetAllDatesToNowCommand()
{
    this.selectedIncident.Start = DateTime.Now;
    // etc.
}