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
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>
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:
Ma 2.0 non ha avuto alcun WPF, vuoi dire 3.0? – bitbonk
- 1. Cambia utente utente PhoneGap
- 2. Il marshalling di un'interfaccia di marshalling mi fornisce un marshaller per il proxy o l'interfaccia originale?
- 3. ASP.Net Tracciamento attività utente nel database
- 4. Controlla se il nome utente esiste nel database con AJAX
- 5. DataContext del controllo utente WPF è Null
- 6. Come memorizzare campi utente personalizzati nel database
- 7. Xcode Thread 1: È sempre il thread dell'interfaccia utente principale?
- 8. Laravel: Come inserisco il primo utente nel database
- 9. Come gestire il thread C# WPF nel modello di visualizzazione MVVM
- 10. Qual è la differenza tra il thread di Dispatcher e il thread dell'interfaccia utente
- 11. Gestione degli eventi del controllo utente WPF
- 12. Interfaccia utente semantica - Cambia tema
- 13. Cambia immagine utilizzando il trigger WPF MVVM
- 14. come posso ottenere il genitore del controllo utente wpf
- 15. Ottieni il nome del controllo utente genitore WPF C#
- 16. WPF Sicurezza thread threading?
- 17. SVN cambia nome utente
- 18. Il proprietario del database SID registrato nel database master differisce dal proprietario del database SID
- 19. Cambia proprietario del diagramma del database in SQL Server 2005
- 20. Cambia nome utente account GitHub
- 21. Utilizzo di BigDecimal nel marshalling JAXB
- 22. Controllo WPF sulla filettatura dell'interfaccia utente separata?
- 23. Cambia le impostazioni del colore nel completami
- 24. Perché solo il thread dell'interfaccia utente è autorizzato a modificare l'interfaccia utente?
- 25. Database utente singolo o database multiutente
- 26. Impossibile salvare il contenuto del modulo nel database
- 27. Cambia utente con Firebase Autenticazione utente Google
- 28. Evidenzia celle in WPF DataGrid quando il valore associato cambia
- 29. Il thread principale è lo stesso del thread UI?
- 30. modello per bloccare utente Java Swing nel thread di lavoro
Che dire di tipi scalari complessi? Cosa succede se ho una proprietà nel mio ViewModel di tipo "MyCompositeObject"? – bitbonk
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. –
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