MVVM、Prism 和服务发现

发布于 2024-07-28 22:51:06 字数 2077 浏览 6 评论 0原文

我正在使用 MVVM 模式和 Prism 框架编写一个应用程序(Silverlight 和 WPF)。 在我的应用程序中,我有一个包含客户列表的网格。 在此之下,我提供了呈现客户详细信息的各种视图。 所有信息均来自 WCF 服务,该服务提供来自查询的数据以及在收到数据时触发事件的回调。 当网格中的所选项目发生更改时,详细信息也会更新。 还有一个过滤视图可以控制详细信息的日期范围。

我还需要实现一组类似的视图,但针对特定的客户。 提供的信息是相同的,因此显然最好重用相同的视图和模型类。

我最初的想法是为这两种场景构建一个位于模型和 WCF 服务之间的单独的中间服务。 然后,我通过按名称注册实例将模型绑定到特定服务。

不幸的是,这意味着我必须自己实例化许多类,而不是依赖我更喜欢的依赖注入。

那么,对于所有 MVVM 专家来说,应该如何构建视图、模型和服务才能最好地利用 Prism 框架的功能并促进代码重用?

非常感谢!

==== 编辑:添加以下文本和示例 ====

这是一个简单的示例,我希望它能解释我想要完成的任务。

public class CustomerViewModel : ICustomerViewModel
{
    public ICustomerView View { get; private set; }
    private readonly ICustomerService customerService { get; set; }
    private Customer customer;

    public CustomerViewModel(ICustomerView view, ICustomerService service, IEventAggregator eventAggregator)
    {
        customerService = service;

        eventAggregator.GetEvent<SelectedCustomerChangedEvent>().Subscribe(CustomerChanged);
        eventAggregator.GetEvent<CustomerInfoUpdatedEvent>().Subscribe(CustomerUpdated);

        View = view;
        View.Model = this;
    }

    public string Name
    {
        get
        {
            return customer.Name;
        }
    }

    public string Email
    {
        get
        {
            return customer.Email;
        }
    }

    public void CustomerChanged(int customerId)
    {
        customerService.RequestCustomerInfo(customerId);
    }

    public void CustomerUpdated(Customer customer)
    {
        this.customer = customer;
    }
}

该客户视图模型基于当前设计,其中客户位于网格中。 选择客户会触发 SelectedCustomerChangedEvent,这将导致视图模型请求信息。

它由使用回调机制提供数据的底层 WCF 服务提供(数据可能需要很长时间才能检索/计算,因此简单的 WCF 调用将无法工作)。 这很好用。 问题是我想在应用程序的不同区域重用相同的视图和模型,以显示有关特定客户而不是当前选定客户的信息。

我最初的想法是创建一个中间服务,用于处理列表的 SelectedCustomerChangedEvent 以及打开客户特定视图时的类似事件。 然后,它将通过相同的 CustomerInfoUpdatedEvent 向模型提供数据。

问题是,由于我现在有两个实现相同接口的服务,因此我需要为它们命名,然后让视图模型以某种方式知道要从容器中检索哪一个。

我知道我可能犯了一个设计错误。 好消息是我有时间修复它,但我不知道如何修复它。

I'm writing an application (Silverlight and WPF) using the MVVM pattern and the Prism framework. In my application I have a grid that contains a list of customers. Under that, I various views that present customer details. All of the information is fed from a WCF service that provides data from queries as well as callbacks which fire events when the data has been received. The detail information is updated when the selected item in the grid is changed. There is also a filtering view that controls the date range for the detailed information.

I also need to implement a similar set of views, but for a specific customer. The information presented is the same, so obviously it would be best to reuse the same view and model classes.

My initial thought was to build a separate intermediate service that sat between the models and the WCF service for both scenarios. I would then bind the models to the specific service by registering instances by name.

Unfortunately, this would mean that I would have to instantiate a lot of the classes myself instead of relying on dependency injection which I would prefer.

So, for all the MVVM gurus out there, how should the views, models, and services be structured to best use the features of the Prism framework and promote code-reuse?

Many thanks!

==== Edit: added following text and example ====

Here is a simple example that I hope explains what I'm trying to accomplish.

public class CustomerViewModel : ICustomerViewModel
{
    public ICustomerView View { get; private set; }
    private readonly ICustomerService customerService { get; set; }
    private Customer customer;

    public CustomerViewModel(ICustomerView view, ICustomerService service, IEventAggregator eventAggregator)
    {
        customerService = service;

        eventAggregator.GetEvent<SelectedCustomerChangedEvent>().Subscribe(CustomerChanged);
        eventAggregator.GetEvent<CustomerInfoUpdatedEvent>().Subscribe(CustomerUpdated);

        View = view;
        View.Model = this;
    }

    public string Name
    {
        get
        {
            return customer.Name;
        }
    }

    public string Email
    {
        get
        {
            return customer.Email;
        }
    }

    public void CustomerChanged(int customerId)
    {
        customerService.RequestCustomerInfo(customerId);
    }

    public void CustomerUpdated(Customer customer)
    {
        this.customer = customer;
    }
}

This customer view model based on the current design where the customers are in a grid. Selecting a customer fires the SelectedCustomerChangedEvent which will cause the view model to request information.

It is fed from an underlying WCF service that is using a callback mechanism to provide data (the data can take a long time to retrieve / calculate so a simple WCF call won't work). This works just fine. The problem is that I want to reuse this same view and model in a different area of the application that displays information about a specific customer instead of the current selected customer.

My initial thought was to create an intermediate service that handled the SelectedCustomerChangedEvent for the list and a similar event when the customer-specific view is opened. It would then provide data to the model through the same CustomerInfoUpdatedEvent.

The problem is that since I would now have 2 services that implement the same interface, I would need to name them and then have the view model somehow know which one to retrieve from the container.

I know I've probably made a design error. The good news is that I have time to fix it, but I'm not sure how to fix it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔戏命师 2024-08-04 22:51:06

如果所有客户(包括您的特定客户)的 Customer 类都相同,则使用单一服务、相同的视图和相同的模型。

你能告诉我们为什么这行不通吗?

If the Customer class is the same for all customers (including your specific customer), then use a single service, the same views, and the same model.

Can you tell us why this would not work?

栀子花开つ 2024-08-04 22:51:06

嗯...这里有很多信息,但我会尝试一下。

确实没有理由让这件事像你所尝试的那样复杂化。 感觉就像您正在从 WCF 服务接收回调事件......我是对的吗? 如果是这样,并且传入的 WCF 回调与用户正在查看的客户相关,您希望更新 UI。 我将根据这些假设进行工作...如果我误解了,请告诉我。

我想你几乎已经拥有了你需要的东西。 我认为您需要做的就是以下操作:

  1. 从 WCF 回调处理程序中,使用 EventAggregator 引发一个事件,传递新客户信息以及客户 ID
  2. 从任何 ViewModel 的构造函数中,订阅 CustomerUpdated 事件并为您在视图模型中查看的客户 ID 添加过滤器。 您错过了这一点,但它很重要,否则您将得到大量不一定与实例化的 ViewModel 相关的事件。 本快速入门中有此技术的示例: http://msdn.microsoft .com/en-us/library/dd458918.aspx

再说一遍,这是我为理解您想要实现的目标而做出的最大努力。 如果不是,请告诉我们。

Hmm... there is a lot of information here, but I will take a stab at this.

There's really no reason to complicate this as much as you are trying. It feels like you are receiving callback events from your WCF service... am I right? If so, you want to update the UI if the incoming WCF callback pertains to a customer that the user is viewing. I'll work from these assumptions... let me know if I misunderstand.

I think you have almost what you need. I think all you need to do is the following:

  1. From your WCF callback handler, raise an event with the EventAggregator passing the new customer information along with the customer ID.
  2. From any ViewModel's constructor, subscribe to the CustomerUpdated event and add a filter for the customer ID you are looking at in your view model. You are missing this, but it's critical, otherwise you will get a firehose of events that don't pertain necessarily to your instantiated ViewModel. There is a sample of this technique in this quickstart: http://msdn.microsoft.com/en-us/library/dd458918.aspx

Again, this is my best effort at understanding what you are trying to accomplish. Let us know if it's not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文