WPF MVVM textBox 文本绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13745901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:31:16  来源:igfitidea点击:

WPF MVVM textBox Text Binding

c#wpfmvvminotifypropertychanged

提问by Nick Williams

I am just getting started with MVVM so apologies if I've done something really stupid. I tried writing a very simple test to see if I could remember everything, and for the life of me I can't see why its not working.

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

In my view I have a textBox where its text property is bound to a value in the ViewModel. Then when pressing a button the value should be altered and the textBox update.

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

I can see the value does alter (I have added a MessageBox.Show() line in the buttom press command) however the textBox does not update.

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

I assume that this means I have not properly implemented the INotifyPropertyChangedevent properly but am unable to see my mistake.

我认为这意味着我没有正确实施该INotifyPropertyChanged事件,但无法看到我的错误。

Could anyone point me in the right direction?

有人能指出我正确的方向吗?

Here is the code:

这是代码:

View

看法

<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>

Behind View

后视图

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel.MainWindowViewModel();
    }
}

ViewModel

视图模型

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;
    }
}

Model

模型

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

Commands

命令

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

Sorry for such a long post and it being a spot my mistake post but I've looked at it for so long and I don't know what I'm doing wrong

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

Thanks!

谢谢!

回答by Agustin Meriles

The Problem that you have is that you are changing the wrong Property. Instead of changing the HelloWorld.MessageProperty, you are changing MainWindowViewModel.HelloWorldproperty. Your code will work OK if you change this line:

您遇到的问题是您正在更改错误的属性。您不是在更改HelloWorld.Message属性,而是在更改MainWindowViewModel.HelloWorld属性。如果您更改此行,您的代码将正常工作:

public void UpdateTime()
{
    helloWorld = new HelloWorld("The time is " + DateTime.Now.ToString("HH:mm:ss"));
}

For this one

对于这个

public void UpdateTime()
{
    helloWorld.Message = "The time is " + DateTime.Now.ToString("HH:mm:ss");
}

If you want to keep your original code, then you need to implement INotifyPropertyChanged for your ViewModel, and rise the event when you change helloWorldobject.

如果要保留原始代码,则需要为 ViewModel 实现 INotifyPropertyChanged,并在更改helloWorld对象时引发事件。

Hope this helps

希望这可以帮助

回答by CodeWarrior

I think you need to implement PropertyChanged notification on your ViewModel. You are creating a new HelloWorld in the UpdateTime method, but the UI doesn't know it.

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

Edit

编辑

I have a ViewModel base class which I derive all of my ViewModels from. It implements INotifyPropertyChanged, and has references to my relay command classes, and some other common stuff. I recommend always having INotifyPropertyChanged implemented on the ViewModel. The ViewModel is there to expose data to the UI, and it cant do that for data that changes without that interface.

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

回答by user1064519

i think your ViewModel needs to implement INotifyPropertyChanged too, or you can set the DataContext before you call InitializeComponents(), if you do that you should change your code to NOT create a new instance every update like Agustin Meriles said.

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

回答by zzfima

  1. i think you mistake Model and VM: Model is MainWindowViewModel and VM is HelloWorld
  2. In your VM (class HelloWorld ) you need use your model

    So, your classes will look like:

        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; }
        }
    }
    
  1. 我想你搞错了 Model 和 VM:Model 是 MainWindowViewModel 而 VM 是 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; }
        }
    }
    

inset inside your ICommands

插入您的 ICommands 中