感谢tencntraze的建议,这个问题已经解决了。
请参阅此问题的底部和tencntraze解决方案的答案。
我的程序中有一个相当奇怪的错误,我正在挣扎。
我正在开发一个MVVM应用程序,我在View中有一个简单的ListBox,其ItemsSource绑定到一个ObservableCollection字符串。每当我向这个集合中添加一个项目时,它/ /会/触发一个事件来通知集合已经发生了变化,但这在运行时没有反映在GUI上,除非我在程序运行时尝试手动调整窗口大小,几乎就像调整窗口大小一样强制GUI刷新。
相关控制的XAML如下
<ListBox ItemsSource="{Binding Path=LogWindow}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,0,0,0" />
你可以看到的是完全正常的。在我的ViewModel中,我有一个名为LogWindow的公共属性,定义如下
public ObservableCollection<string> LogWindow
{
get
{
return _logWindow;
}
set
{
_logWindow = value;
OnPropertyChanged("LogWindow");
}
}
此私人会员如下
private ObservableCollection<string> _logWindow;
在ViewModel构造函数中,我初始化_logWindow并将LogWindow CollectionChanged事件连接到处理程序,处理程序又触发PropertyChanged通知。
我的代码如下
public MainWindowViewModel(IDialogService dialogService)
{
... skipped for brevity
LogWindow = new ObservableCollection<string>();
LogWindow.CollectionChanged += LogWindow_CollectionChanged;
...
}
CollectionChanged事件处理程序如下
void LogWindow_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("LogWindow");
}
最后,当我的View收到来自Model的新消息的通知时,我将一个新字符串添加到observable集合中,如下所示
LogWindow.Add(_vehicleWeightManager.SerialMessage);
当LogWindow.Add发生时,我的事件监听器触发并且我的断点被点击以确认代码到达那么远,如下图所示
在此之后我的代码调用从我的ViewModelBase继承的OnPropertyChanged函数,这对我的其他GUI元素(如标签等)运行良好,因此几乎可以肯定不是问题。
我将一块手表应用于LogWindow以跟踪该集合确实被添加到了,它如下图所示
所以在这个阶段我很茫然。如果我以某种方式调整窗口大小,我的GUI将只会更新,否则没有可视更新。数据存在于绑定属性中,并且当新项目添加到属性时,GUI会被警告...是否有人有任何可能有帮助的洞察力?
感谢tencntraze和kallocain的建议已经解决了。
问题是由另一个尝试添加到LogWindow集合的线程引起的,这导致了错误的行为。我没有按照建议使用Dispatcher,而是使用了如下的TaskFactory代码。
TaskFactory uiFactory;
...
...
public MainWindowViewModel(IDialogService dialogService)
{
...
_logWindow = new ObservableCollection<string>();
uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
...
...
void _vehicleWeightManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
...
if (e.PropertyName == "VehicleWeight")
{
// Marshal the SerialMessage property to the GUI thread.
uiFactory.StartNew(() => LogWindow.Add(_vehicleWeightManager.SerialMessage.Replace("\n", ""))).Wait();
}
}
可以找到上述方法的进一步阅读here
答案 0 :(得分:4)
如果您在另一个线程上收到消息,则需要将其调用回UI线程,否则可能会出现不可预测的行为。有时候这是一个例外,其他时候它什么也不做。
this.Dispatcher.BeginInvoke(new Action(() =>
{
LogWindow.Add(_vehicleWeightManager.SerialMessage);
}));