Dan*_*ane 5 c# wpf user-interface observablecollection mvvm
感谢tencntraze的建议,这个问题已经解决了。
请参阅此问题的底部和 tencntraze 的答案以获取解决方案。
我的程序中有一个相当奇怪的错误,我目前正在努力解决它。
我正在开发一个 MVVM 应用程序,我的视图中有一个简单的 ListBox,其 ItemsSource 绑定到字符串的 ObservableCollection。每当我向此集合添加一个项目时,它都会触发一个事件来通知集合已更改,但这在运行时不会反映在 GUI 上,除非我尝试在程序运行时手动调整窗口大小,几乎就像调整窗口大小会强制 GUI 刷新一样。
相关控件的XAML如下
<ListBox ItemsSource="{Binding Path=LogWindow}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,0,0,0" />
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,这是完全正常的。在此视图的 ViewModel 中,我有一个名为 LogWindow 的公共属性,定义如下
public ObservableCollection<string> LogWindow
{
get
{
return _logWindow;
}
set
{
_logWindow = value;
OnPropertyChanged("LogWindow");
}
}
Run Code Online (Sandbox Code Playgroud)
其私人成员如下
private ObservableCollection<string> _logWindow;
Run Code Online (Sandbox Code Playgroud)
在 ViewModel 构造函数中,我初始化 _logWindow 并将 LogWindow CollectionChanged 事件连接到处理程序,该处理程序进而触发 PropertyChanged 通知。
我的代码如下
public MainWindowViewModel(IDialogService dialogService)
{
... skipped for brevity
LogWindow = new ObservableCollection<string>();
LogWindow.CollectionChanged += LogWindow_CollectionChanged;
...
}
Run Code Online (Sandbox Code Playgroud)
CollectionChanged事件处理程序如下
void LogWindow_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("LogWindow");
}
Run Code Online (Sandbox Code Playgroud)
最后,当我的视图收到来自模型的新消息的通知时,我将一个新字符串添加到可观察集合中,如下所示
LogWindow.Add(_vehicleWeightManager.SerialMessage);
Run Code Online (Sandbox Code Playgroud)
当 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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您在另一个线程上接收消息,则需要将其调用回 UI 线程,否则可能会出现不可预测的行为。有时这是一个例外,有时却什么也不做。
this.Dispatcher.BeginInvoke(new Action(() =>
{
LogWindow.Add(_vehicleWeightManager.SerialMessage);
}));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10429 次 |
| 最近记录: |