5

我刚刚开始使用 MVVM,如果我做了一些非常愚蠢的事情,我深表歉意。我尝试编写一个非常简单的测试,看看我是否能记住所有内容,而对于我的生活,我不明白为什么它不起作用。

在我看来,我有一个文本框,它的文本属性绑定到 ViewModel 中的一个值。然后,当按下按钮时,应该更改值并更新文本框。

我可以看到值确实发生了变化(我在按钮按下命令中添加了 MessageBox.Show() 行)但是文本框没有更新。

我认为这意味着我没有正确实施该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();
        }
    }
}

抱歉这么长的帖子,这是我的错误帖子,但我已经看了很长时间,我不知道我做错了什么

谢谢!

4

4 回答 4

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对象时触发事件。

希望这可以帮助

于 2012-12-06T14:47:50.490 回答
2

我认为您需要在 ViewModel 上实现 PropertyChanged 通知。您正在 UpdateTime 方法中创建一个新的 HelloWorld,但 UI 不知道它。

编辑

我有一个 ViewModel 基类,我从中派生出所有的 ViewModel。它实现了 INotifyPropertyChanged,并引用了我的中继命令类和其他一些常见的东西。我建议始终在 ViewModel 上实现 INotifyPropertyChanged。ViewModel 用于向 UI 公开数据,而对于没有该接口的数据更改,它无法做到这一点。

于 2012-12-06T14:49:44.210 回答
1

我认为您的 ViewModel 也需要实现 INotifyPropertyChanged,或者您可以在调用 InitializeComponents() 之前设置 DataContext,如果这样做,您应该更改代码以不像 Agustin Meriles 所说的那样每次更新都创建一个新实例。

于 2012-12-06T14:54:20.313 回答
1
  1. 我认为你弄错了模型和虚拟机:模型是 MainWindowViewModel 而虚拟机是 HelloWorld

  2. 在您的 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 中插入

于 2012-12-06T14:56:11.110 回答