Ich habe versucht, einen Griff auf die Rx-Bibliothek zu bekommen und arbeiten es in WPF mit MVVM aus. Ich brach meine Anwendung in Komponenten wie Repository und das ViewModel. Mein Repository in der Lage, eine Sammlung von Studenten einer nach dem anderen bereitzustellen, aber der Moment, den ich versuche, in die Ansicht gebunden ObservableCollection es wirft einen Thread-Fehler hinzufügen. Ich 'd apreciate einige Zeiger auf, um diese Arbeit für mich zu erhalten.
Antworten
Zu viele Anzeigen?Sie müssen den Synchronisationskontext korrekt einstellen, indem Sie
ObserveOn(SynchronizationContext.Current)
Siehe diesen Blogbeitrag
für ein Beispiel.
Hier ist ein Beispiel, das für mich funktioniert:
<Page.Resources>
<ViewModel:ReactiveListViewModel x:Key="model"/>
</Page.Resources>
<Grid DataContext="{StaticResource model}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Start" Command="{Binding StartCommand}"/>
<ListBox ItemsSource="{Binding Items}" Grid.Row="1"/>
</Grid>
public class ReactiveListViewModel : ViewModelBase
{
public ReactiveListViewModel()
{
Items = new ObservableCollection<long>();
StartCommand = new RelayCommand(Start);
}
public ICommand StartCommand { get; private set; }
private void Start()
{
var observable = Observable.Interval(TimeSpan.FromSeconds(1));
//Exception: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
//observable.Subscribe(num => Items.Add(num));
// Works fine
observable.ObserveOn(SynchronizationContext.Current).Subscribe(num => Items.Add(num));
// Works fine
//observable.ObserveOnDispatcher().Subscribe(num => Items.Add(num));
}
public ObservableCollection<long> Items { get; private set; }
}
Läuft Ihr Code in einem Hintergrund-Thread? Da es die Benutzeroberfläche betrifft, kann eine View-gebundene ObservableCollection nur auf dem UI/Dispatcher-Thread aktualisiert werden.
Siehe WPF ObservableCollection Thread Sicherheit für ein ähnliches Problem.
Alle Änderungen an der Benutzeroberfläche sollten von der Dispatcher
Thema. Eine gute Praxis, wenn Sie anthoer Thread ständige Änderung der Ansicht Modell ist zu erzwingen Eigenschaft Setter, um die Dispatcher-Thread verwenden. In diesem Fall stellen Sie sicher, dass Sie nicht ein UI-Element auf einem anderen Thread ändern.
Versuchen Sie es:
public string Property
{
set
{
Dispatcher.BeginInvoke(()=> _property = value ) ;
OnPropertyChanged("Property");
}
get
{
return _property;
}
}