wpf mvvm 绑定列表;从后台线程到列表框
我对 wpf 和 mvvm 很陌生,所以这可能是一个简单的问题,但我希望有人可以向我解释一下。我的模型中有一个类,它所做的只是轮询进程,如果它看到“calc”正在运行,它会将其进程 ID 添加到列表中。如果您关闭 calc.exe,它会将其从列表中删除。如果列表发生更改,则会触发事件。在我的 ViewModel 中,我订阅该事件并更新触发 PropertyChanged 的属性。现在,如果我的属性是视图模型中的列表,那么我的视图中的绑定不会正确更新。如果我将列表更改为模型和视图模型中的 ObservableCollection,则会出现跨线程问题。但是,如果我将列表留在模型中,并将 ViewModel 中的属性更改为 ObservableCollection,并将列表的值复制到可观察集合中,一切都会按预期工作......我不明白,我真的吗?需要进行复制才能使列表框中的绑定正常工作吗?
I'm pretty new to wpf and mvvm so this may be a easy question but I'm hoping someone can explain it to me. I have a class in my model that all it does is polls processes and if it see that "calc" is running it adds it process id to a List. If you close calc.exe it removes it from the List. If the List changes it fires and event. In my ViewModel i subscribe to that event and update my property that fires off PropertyChanged. Now if my Property is a List in the view model then my binding in my view does not update correctly. If I changed my List to an ObservableCollection in my Model and ViewModel then i get a cross thread issue. However, if i leave my List in my model and change my property in my ViewModel to a ObservableCollection and copy the values of the the list into an observable collection everything works as expected.... I don't get it, do i really need to do the copy to get the binding in my ListBox to work properly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看一下 Cinch 实现的 DispatcherNotifiedObservableCollection。如果需要,它将自动使用调度程序。阅读本文以查看其代码:
http://www.codeproject.com /KB/WPF/CinchIII.aspx#ObsCol
Take a look at the DispatcherNotifiedObservableCollection that Cinch implements. It will automatically use the Dispatcher if need be. Read this article to see the code for it:
http://www.codeproject.com/KB/WPF/CinchIII.aspx#ObsCol
您需要从调度线程更新可观察集合。
类似的东西(技术上/语法上不正确,但伪接近)
You need to update the observable collection from the dispatch thread.
Something like (not technically/syntactically correct, but psuedo-close)
实现此功能的更好方法是通过 ViewModel 中的属性公开模型,并将 ListBox 绑定到 Model.ObservableList。并在向此列表添加和删除项目时使用约翰的建议。这不需要您将列表中的值复制到可观察集合。
因此,您的 viewModel 代码将类似于
xaml 中的绑定:
其中 ObservableList 属性返回您的 ObservableCollection。
由于 WPF 中的所有 UI 元素都具有线程关联性(与 Dispatcher 线程),因此对 UI 的任何更新都应通过 Dispatcher 进行封送。您可以使用 Dispatcher.Invoke 通过 Dispatcher 编组调用。在这种情况下,您的视图、viewModel 和 Model 驻留在 Dispatcher 线程中,因此任何通过 viewModel 或 Model 更新 UI 的调用都需要您调用 Dispatcher.Invoke。
A better way to achieve this functionality, is expose the Model via a property in the ViewModel, and bind the ListBox to Model.ObservableList. And use John's suggestion when adding and removing items to this list. This will not require you to copy the values from list to an observablecollection.
So your viewModel code would like
The binding in xaml:
where the ObservableList property returns your ObservableCollection.
As all UI elements in WPF have thread affinity (to the Dispatcher thread), any updates to the UI should be marshaled via the Dispatcher. You can marshal calls via the Dispatcher, using Dispatcher.Invoke. In this case, your view, viewModel and Model reside in the Dispatcher thread, so any call to update the UI via the viewModel or Model, would require you to call Dispatcher.Invoke.