2009-08-24 12 views
15

Ho appena notato che quando si modificano le proprietà associate nel mio ViewModel (MVVM) da un thread di lavoro in background non ottengo alcuna eccezione e la vista viene aggiornata correttamente. Questo significa che posso tranquillamente fare affidamento su wpf databinding che esegue il marshalling di tutti i cambiamenti nel ViewModel nel thread UI? Penso di aver letto da qualche parte che si dovrebbe essere sicuri (nello ViewModel) che INotifyPropertyChanged.PropertyChanged venga attivato sul thread dell'interfaccia utente. Questo è cambiato in 3.5 o qualcosa del genere?Il marshalling del database WPF cambia nel thread dell'interfaccia utente?

risposta

12

Sì per scalari, no per le raccolte. Per le raccolte, avrai bisogno di una raccolta specializzata che effettua il marshal per te o esegui manualmente il marshalling sul thread dell'interfaccia utente tramite lo Dispatcher.

Potrebbe essere stato letto che INotifyCollectionChanged.CollectionChanged deve essere attivato sul thread dell'interfaccia utente, perché semplicemente non è vero di INotifyPropertyChanged.PropertyChanged. Di seguito è riportato un esempio molto semplice che dimostra le modifiche alle proprietà dei marshall dei WPF.

Window1.xaml.cs:

using System.ComponentModel; 
using System.Threading; 
using System.Windows; 

namespace WpfApplication1 
{ 
    public partial class Window1 : Window 
    { 
     private CustomerViewModel _customerViewModel; 

     public Window1() 
     { 
      InitializeComponent(); 
      _customerViewModel = new CustomerViewModel(); 
      DataContext = _customerViewModel; 

      var thread = new Thread((ThreadStart)delegate 
      { 
       while (true) 
       { 
        Thread.Sleep(2000); 
        //look ma - no marshalling! 
        _customerViewModel.Name += "Appended"; 
        _customerViewModel.Address.Line1 += "Appended"; 
       } 
      }); 

      thread.Start(); 
     } 
    } 

    public abstract class ViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged(string propertyName) 
     { 
      var handler = PropertyChanged; 

      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 

    public class CustomerViewModel : ViewModel 
    { 
     private string _name; 
     private AddressViewModel _address = new AddressViewModel(); 

     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       if (_name != value) 
       { 
        _name = value; 
        OnPropertyChanged("Name"); 
       } 
      } 
     } 

     public AddressViewModel Address 
     { 
      get { return _address; } 
     } 
    } 

    public class AddressViewModel : ViewModel 
    { 
     private string _line1; 

     public string Line1 
     { 
      get { return _line1; } 
      set 
      { 
       if (_line1 != value) 
       { 
        _line1 = value; 
        OnPropertyChanged("Line1"); 
       } 
      } 
     } 
    } 
} 

Window1.xaml:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <TextBox Text="{Binding Name}"/> 
     <TextBox Text="{Binding Address.Line1}"/> 
    </StackPanel> 
</Window> 
+0

Che dire di tipi scalari complessi? Cosa succede se ho una proprietà nel mio ViewModel di tipo "MyCompositeObject"? – bitbonk

+0

Sì, le modifiche in qualsiasi punto lungo un percorso di proprietà verranno eseguite correttamente nel marshalling, a meno che non ci sia una raccolta in quel percorso. –

+0

La prima volta che ho letto che i cambi di proprietà dovrebbero essere sul thread dell'interfaccia utente, era qui: http://blogs.msdn.com/dancre/archive/2006/07/23/676300.aspx – bitbonk

1

Credo che con 2.0 e precedenti incarnazioni di .NET che avrebbe ricevuto un InvalidOperationException dovuta per eseguire il thread di affinità quando si esegue l'esempio di cui sopra (il collegamento pubblicato da bitbonk è datato 2006).

Ora, con 3.5, WPF sembra effettuare il marshalling delle modifiche alle proprietà del thread in background sul dispatcher.

Quindi, in breve, dipende da quale versione di .NET si sta puntando. Spero che questo chiarisca ogni confusione.

Uno dei miei compagni di Lab49'ers bloggato su qui nel 2007:

http://blog.lab49.com/archives/1166

+0

Ma 2.0 non ha avuto alcun WPF, vuoi dire 3.0? – bitbonk

Problemi correlati