我正在使用SerialPort类中的事件侦听器从串行端口读取数据。在我的事件处理程序中,我需要在窗口中更新许多(30-40个)控件,其中xml数据来自串口。
我知道我必须使用myControl.Dispatcher.Invoke()来更新它,因为它位于不同的线程上,但有没有办法一起更新许多控件,而不是为每个控件执行单独的Invoke调用(即myCon1) .Dispatcher.Invoke(),myCon2.Dispatcher.Invoke()等)?
我正在寻找类似于在容器上调用Invoke,并单独更新每个子控件的东西,但我似乎无法弄清楚如何实现这一点。
谢谢!
答案 0 :(得分:1)
您需要做的是使用MVVM。
将控件绑定到ViewModel上的公共属性。您的VM可以侦听串行端口,解析xml数据,更新其公共属性,然后使用INotifyPropertyChanged告知UI更新其绑定。
我建议使用此路由,因为您可以批量通知,如果必须,可以使用Dispatcher在UI线程上调用事件。
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调用一次。但那种方法很糟糕。