5

私はMVVMを使い始めたばかりなので、本当にばかげたことをした場合は申し訳ありません。すべてを覚えているかどうかを確認するために、非常に簡単なテストを作成しようとしましたが、私の人生では、なぜ機能しないのかわかりません。

私の見解では、テキスト プロパティが ViewModel の値にバインドされている textBox があります。次に、ボタンを押すと、値が変更され、textBox が更新されます。

値が変更されていることがわかります (ボタンを押すコマンドに 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();
        }
    }
}

こんなに長い投稿で申し訳ありませんが、それは私の間違いの投稿ですが、長い間見てきましたが、何が間違っているのかわかりません

ありがとう!

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

ICommands 内に挿入

于 2012-12-06T14:56:11.110 に答える
1

ViewModel も INotifyPropertyChanged を実装する必要があると思います。または、InitializeComponents() を呼び出す前に DataContext を設定することもできます。その場合、Agustin Meriles が言ったように、更新ごとに新しいインスタンスを作成しないようにコードを変更する必要があります。

于 2012-12-06T14:54:20.313 に答える