WPF MVVM textBox Associazione di Testo

Ho appena iniziato con MVVM quindi mi scuso se ho fatto qualcosa di veramente stupido. Ho provato a scrivere un test molto semplice per vedere se riuscivo a ricordare tutto, e per la vita di me non riesco a vedere perché non è il suo funzionamento.

Nel mio punto di vista ho una textBox dove la proprietà text è associato a un valore nel ViewModel. Quindi quando si preme un tasto, il valore deve essere modificato e la casella di testo di aggiornamento.

Posso vedere il valore non altera (ho aggiunto una MessageBox.Show() riga in fondo premere comando) tuttavia la casella di testo non si aggiorna.

Presumo che questo significa che non ho implementato correttamente il INotifyPropertyChanged evento correttamente, ma non riesco a vedere il mio errore.

Potrebbe qualcuno mi punto nella giusta direzione?

Ecco il codice:

Vista

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

Dietro Di Vista

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

Modello

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

Comandi

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

Scusate per questo lungo post, essendo un posto errore mio post, ma ho guardato così a lungo, e non so cosa sto facendo di sbagliato

Grazie!

Suppongo che anche tu hai bisogno di avere una proprietà di notifica di variazione sul helloWorld proprietà, perché si sta utilizzando il percorso di associazione helloWorld.Message.

OriginaleL’autore Nick Williams | 2012-12-06

4 Replies
  1. 6

    Il Problema che hai è che si sta cambiando la Proprietà non valido. Invece di cambiare il HelloWorld.Message Proprietà, si modifica MainWindowViewModel.HelloWorld proprietà. Il codice funziona bene se si modifica questa riga:

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

    Per questo

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

    Se si desidera mantenere il vostro codice originale, quindi è necessario implementare INotifyPropertyChanged per il ViewModel, e aumentare l’evento quando si cambia helloWorld oggetto.

    Spero che questo aiuta

    Sì che funziona ora. Che dovrebbe essere abbastanza ovvio, in realtà. Non sono sicuro VMMV è tutto è incrinato fino a essere :P. È accettabile per implementare la modifica di una proprietà nel ViewModel?
    la vista-il modello è in realtà dove INotifyPropertyChanged deve essere attuata in primo luogo! Ricordate che il view model è la classe a cui verrà associata la UI e questo durante il processo di associazione che l’interfaccia utente è in grado di suscribe per gli eventi di visualizzazione del modello.
    di più di un modello 😉 si dovrebbe implementare sempre INotifyPropertyChanged nelle classi si sono associazione, in caso contrario, può causare memoryleaks. code.logos.com/blog/2008/10/…
    Sì!, è totalmente accettato di avere INotifyPropertyChanged nel ViewModel. Andare per esso
    Tenete a mente che molti dei quadri che vengono utilizzati per i modelli (Entity Framework viene in mente) esporre le loro classi del modello con INotifyPropertyChanged per impostazione predefinita. Questo consente di esporre i dati, ma il ViewModel espone le proprietà che la Vista ha bisogno per come presentare i dati. Se non ricevi notifiche che qualcosa è cambiato, quindi si avrà viste statiche non approfittare di molte delle caratteristiche più potenti di WPF.

    OriginaleL’autore Agustin Meriles

  2. 2

    Penso che è necessario implementare PropertyChanged notifica del ViewModel. La creazione di un nuovo HelloWorld in UpdateTime metodo, ma l’interfaccia utente non lo sa.

    Modifica

    Ho una classe di base ViewModel che mi derivano tutti il mio Viewmodel. Implementa INotifyPropertyChanged, e ha riferimenti al mio relè classi di comando, e di alcuni altri comuni roba. Mi consiglia di avere sempre INotifyPropertyChanged implementati nel ViewModel. Il ViewModel è lì per esporre i dati per l’interfaccia utente, e non può fare che per i dati che cambiano senza che interfaccia.

    Questa implementazione sarebbe sicuramente meglio con la notifica di modifica attuata sulla VM, anche se il modello già implementa.
    Infatti. L’idea di avere un ViewModel è quello di avere una classe che fornisce i dati per la Vista in modo che la vista può meglio utilizzare. Anche se i dati visualizzati come testo (in questo caso HelloWorld.Il messaggio) non è servito direttamente dal ViewModel, alla fine è probabile che altre proprietà di essere esposto, pennelli, visibile stati, etc.

    OriginaleL’autore CodeWarrior

  3. 1

    penso che il ViewModel deve implementare INotifyPropertyChanged troppo,
    o è possibile impostare la proprietà DataContext prima di chiamare InitializeComponents(), se non che è necessario modificare il codice per NON creare una nuova istanza di ogni aggiornamento, come Agustin Meriles detto.

    OriginaleL’autore user1064519

  4. 1
    1. penso che l’errore di Modello e VM: il Modello è MainWindowViewModel e VM è HelloWorld
    2. In una macchina virtuale (classe HelloWorld ) è necessario utilizzare il modello

      Così, le lezioni sarà:

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

    inserto all’interno del vostro ICommands

    OriginaleL’autore zzfima

Lascia un commento