Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在哪里更新WPF观测值?_Wpf_Observable - Fatal编程技术网

在哪里更新WPF观测值?

在哪里更新WPF观测值?,wpf,observable,Wpf,Observable,考虑一个案例,其中我有一个WPF应用程序,其中一个StudentView绑定到StudentViewModel中的属性(ObservableCollection)。我还有一个StudentService,它依赖于我的StudentRepository。StudentService提供从UI以外的不同上下文调用的CRUD操作 我的第一个实现在StudentService中有一个可观的集合。虽然它可以使用异步调用和其他方式,但这种设置在很多方面都有反击,感觉不太对劲。尤其是在从各种上下文更新Obse

考虑一个案例,其中我有一个WPF应用程序,其中一个StudentView绑定到StudentViewModel中的属性(ObservableCollection)。我还有一个StudentService,它依赖于我的StudentRepository。StudentService提供从UI以外的不同上下文调用的CRUD操作

我的第一个实现在StudentService中有一个可观的集合。虽然它可以使用异步调用和其他方式,但这种设置在很多方面都有反击,感觉不太对劲。尤其是在从各种上下文更新ObservableCollection时

因此,我认为更好的方法是在表示层(视图/视图模型)中保留观察值,让StudentViewModel从StudentService订阅事件,然后在观察值所在的上下文中更新观察值

所以我的问题是,如果我修改后的方法更好,或者也许还有第三个更好的选择

用示例编辑:

目前我有这个(简化了,但我认为有一些重要的东西):

视图显示学生列表,数据源为my ViewModel:

ItemsControl ItemsSource="{Binding Students.Result, UpdateSourceTrigger=PropertyChanged}">..</ItemsControl>
public class MainViewModel : ViewModelBase
{
   public NotifyTaskCompletion<AsyncObservableCollection<Student>> Students { get; private set; }

   public MainViewModel(IStudentService service)
   {
      Students = new NotifyTaskCompletion<AsyncObservableCollection<Student>>(service.List());
   }
}
itemscontrolitemssource=“{Binding Students.Result,UpdateSourceTrigger=PropertyChanged}”>。。
视图模型:

ItemsControl ItemsSource="{Binding Students.Result, UpdateSourceTrigger=PropertyChanged}">..</ItemsControl>
public class MainViewModel : ViewModelBase
{
   public NotifyTaskCompletion<AsyncObservableCollection<Student>> Students { get; private set; }

   public MainViewModel(IStudentService service)
   {
      Students = new NotifyTaskCompletion<AsyncObservableCollection<Student>>(service.List());
   }
}
public类MainViewModel:ViewModelBase
{
public NotifyTaskCompletion。并从中获取AsyncObservableCollection

My StudentService具有以下接口:

public interface IStudentService
{
   Task<bool> Add(Student student);
   Task<AsyncObservableCollection<Student>> List();
}
公共接口IStudentService
{
任务添加(学生);
任务列表();
}
IStudentService.Add(…)是从后台线程调用的,必须在UI中找到它

现在所有这些都可以工作了,但是AsyncObservaleCollection的锁定(我认为)存在一些问题。所以我想我需要从UI上下文中锁定,但那感觉不对——必须在我的服务中引用UI。我正在考虑的是拉出AsyncObservaleCollection(这是ObservaleCollection)只需从我的服务返回
Task
,就会从服务中触发一些“OnStudentAdded”事件

希望这能让事情变得更清楚


谢谢。

每当添加或删除新项目时,服务需要以某种方式通知视图模型。我同意,最好通过从服务类引发事件或通过公开视图模型可以订阅的
IObservable
来做到这一点

如果从视图直接绑定到的服务中公开公共
ObservableCollection
属性,则无法从服务类中的后台线程更新此集合。该服务在某种程度上依赖于客户端


直接绑定到服务类公开的属性很少是个好主意。您可以在视图模型中创建集合的副本并绑定到此集合,但仍然需要将此集合与服务中定义的集合同步,这并不比订阅事件或
IObservable
和“手动”更新数据绑定源集合在视图模型中。

您使用此事件的目的是什么?您需要了解哪些更改?服务中的哪些更改?通常,可观察集合属于viewmodel。我会犹豫是否将事件放入服务中。viewmodel应该处于控制状态。如果您要轮询后端以获取某些内容,我会编写一个这样做的类,我会d给viewmodel一份副本。这不是神圣的命令,但我发现这种方法对我来说是最容易编写和维护的。@FCin我添加了更多的解释和示例。@EdPlunkett为什么不在服务中使用事件?有没有更优雅的方法让UI了解更改?@Werner“我想我需要一个来自UI上下文的锁,但那感觉不对——必须在我的服务中引用UI"--所以不要这样做。我会这样做,服务只是吐出有人要求的数据--
列表。如果虚拟机想在后台工作程序中请求它,或者将该PCOO的viewmodel版本放在observablecollection中,这取决于虚拟机。正如我所说的,这不是神圣的。如果你有一个lo,我描述的方法可能太粗糙和准备好了不需要保持彼此同步的客户端。但如果不需要,请不要承担额外的复杂性。谢谢,我添加了一些示例代码,更多地说明了我的问题。在我的情况下,你会推荐Rx而不是普通事件吗?不,我不会。没有理由不在添加新学员时简单地引发事件。