wpf: обновить несколько элементов управления через диспетчер
Я читаю данные из последовательного порта, используя прослушиватель событий из класса SerialPort. В моем обработчике событий мне нужно обновить многие (30-40) элементы управления в моем окне, добавив данные xml через последовательный порт.
Я знаю, что должен использовать myControl.Dispatcher.Invoke(), чтобы обновить его, так как он находится в другом потоке, но есть ли способ обновить множество элементов управления вместе, вместо того, чтобы делать отдельный вызов Invoke для каждого (то есть myCon1.Dispatcher.Invoke(), myCon2.Dispatcher.Invoke() и т. Д.)?
Я ищу что-то вроде вызова Invoke для контейнера и индивидуального обновления каждого дочернего элемента управления, но я не могу понять, как этого добиться.
Спасибо!
1 ответ
Что вам нужно сделать, это использовать MVVM.
Вы привязываете свои элементы управления к общедоступным свойствам в ViewModel. Ваша виртуальная машина может прослушивать последовательный порт, анализировать данные xml, обновлять ее общедоступные свойства, а затем использовать INotifyPropertyChanged, чтобы сообщить пользовательскому интерфейсу обновить свои привязки.
Я бы предложил этот маршрут, так как вы можете отправлять уведомления и, если нужно, использовать Dispatcher для вызова события в потоке пользовательского интерфейса.
UI:
<Window ...>
<Window.DataContext>
<me:SerialWindowViewModel />
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding LatestXml}/>
</Grid>
</Window>
SerialWindowViewModel:
public class SerialWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string LatestXml {get;set;}
private SerialWatcher _serialWatcher;
public SerialWindowViewModel()
{
_serialWatcher = new SerialWatcher();
_serialWatcher.Incoming += IncomingData;
}
private void IncomingData(object sender, DataEventArgs args)
{
LatestXml = args.Data;
OnPropertyChanged(new PropertyChangedEventArgs("LatestXml"));
}
OnPropertyChanged(PropertyChangedEventArgs args)
{
// tired of writing code; make this threadsafe and
// ensure it fires on the UI thread or that it doesn't matter
PropertyChanged(this, args);
}
}
И, если это не приемлемо для вас (и вы хотите запрограммировать WPF как приложение winforms), вы можете использовать Dispatcher.CurrentDispatcher, чтобы вызвать один раз, пока вы вручную обновляете все элементы управления в своей форме. Но этот метод воняет.