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, чтобы вызвать один раз, пока вы вручную обновляете все элементы управления в своей форме. Но этот метод воняет.

Другие вопросы по тегам