我刚刚开始使用MVVM,如果我做了一些非常愚蠢的事情,那么道歉。我试着写一个非常简单的测试来看看我是否能记住一切,对于我的生活,我不明白为什么它不能正常工作。
在我看来,我有一个textBox,其text属性绑定到ViewModel中的值。然后当按下按钮时,应该更改值并更新textBox。
我可以看到值确实改变了(我在buttom press命令中添加了MessageBox.Show()行)但是textBox没有更新。
我认为这意味着我没有正确实施INotifyPropertyChanged
事件,但我无法看到我的错误。
有人能指出我正确的方向吗?
以下是代码:
查看
<Window x:Class="Mvvm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBox Height="40" Width="200" Text="{Binding helloWorld.Message, UpdateSourceTrigger=PropertyChanged}"/>
<Button Command="{Binding UpdateTimeCommand}">Update</Button>
</StackPanel>
</Window>
观看背后
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel.MainWindowViewModel();
}
}
视图模型
namespace Mvvm.ViewModel
{
internal class MainWindowViewModel
{
private HelloWorld _helloWorld;
/// <summary>
/// Creates a new instance of the ViewModel Class
/// </summary>
public MainWindowViewModel()
{
_helloWorld = new HelloWorld("The time is " + DateTime.Now.ToString("HH:mm:ss"));
UpdateTimeCommand = new Commands.UpdateTimeCommand(this);
}
/// <summary>
/// Gets the HellowWorld instance
/// </summary>
public HelloWorld helloWorld
{
get
{
return _helloWorld;
}
set
{
_helloWorld = value;
}
}
/// <summary>
/// Updates the time shown in the helloWorld
/// </summary>
public void UpdateTime()
{
helloWorld = new HelloWorld("The time is " + DateTime.Now.ToString("HH:mm:ss"));
}
public ICommand UpdateTimeCommand
{
get;
private set;
}
}
模型
namespace Mvvm.Model
{
class HelloWorld : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public HelloWorld(string helloWorldMessage)
{
Message = "Hello World! " + helloWorldMessage;
}
private string _Message;
public string Message
{
get
{
return _Message;
}
set
{
_Message = value;
OnPropertyChanged("Message");
}
}
private void OnPropertyChanged(string p)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(p));
}
}
}
}
命令
namespace Mvvm.Commands
{
internal class UpdateTimeCommand : ICommand
{
private ViewModel.MainWindowViewModel _viewModel;
public UpdateTimeCommand(ViewModel.MainWindowViewModel viewModel)
{
_viewModel = viewModel;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_viewModel.UpdateTime();
}
}
}
很抱歉这么长的帖子,这是我的错误帖子,但我看了很久,我不知道我做错了什么
谢谢!
答案 0 :(得分:6)
您遇到的问题是您正在更改错误的属性。您正在更改HelloWorld.Message
属性,而不是更改MainWindowViewModel.HelloWorld
属性。如果您更改此行,您的代码将正常工作:
public void UpdateTime()
{
helloWorld = new HelloWorld("The time is " + DateTime.Now.ToString("HH:mm:ss"));
}
对于这个
public void UpdateTime()
{
helloWorld.Message = "The time is " + DateTime.Now.ToString("HH:mm:ss");
}
如果要保留原始代码,则需要为ViewModel实现INotifyPropertyChanged,并在更改helloWorld
对象时升级事件。
希望这有帮助
答案 1 :(得分:2)
我认为您需要在ViewModel上实现PropertyChanged通知。您正在UpdateTime方法中创建一个新的HelloWorld,但UI不知道它。
我有一个ViewModel基类,我从中派生了所有的ViewModel。它实现了INotifyPropertyChanged,并引用了我的中继命令类和其他一些常见的东西。我建议始终在ViewModel上实现INotifyPropertyChanged。 ViewModel用于向UI公开数据,对于没有该接口而发生更改的数据,它无法做到这一点。
答案 2 :(得分:1)
我认为您的ViewModel也需要实现INotifyPropertyChanged, 或者您可以在调用InitializeComponents()之前设置DataContext,如果这样做,您应该将代码更改为不创建新实例,如Agustin Meriles所说的每次更新。
答案 3 :(得分:1)
在您的VM(HelloWorld类)中,您需要使用您的模型
因此,您的课程将如下所示:
using System.ComponentModel;
namespace WpfApplication1
{
public sealed class TextVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private TextInfo _info;
public TextVM()
{
_info = new TextInfo();
}
public string MyText
{
get { return _info.MyText; }
set
{
_info.MyText = value;
OnPropertyChanged("MyText");
}
}
private void OnPropertyChanged(string p)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(p));
}
}
}
}
using System;
namespace WpfApplication1
{
public sealed class TextInfo
{
public TextInfo()
{
MyText = String.Empty;
}
public string MyText { get; set; }
}
}
插入ICommands