通过视图模型传递信息

时间:2014-11-25 21:38:32

标签: c# wpf mvvm

打开客户端文件时,我需要选择的clientId来指示应该查询哪条记录。我正在尝试将ViewModel公开为页面上的静态资源,以便绑定可以轻松访问它。

可以通过此链接找到绑定到静态资源的原因。 http://www.telerik.com/help/silverlight/gridview-troubleshooting-blank-cells.html

// Open an individual record when double-clicked.
public void Open()
{
    if (SelectedItem != null)
    {
        var vm = new LoanViewModel(Events);
        vm.ById(SelectedItem.Id);
        Events.PublishOnUIThread(new ShowTabEvent(vm));
    }
    this.OnPropertyChanged("Items");
}

LoanViewModel.cs

public LoanViewModel()
{ .... Query needs LoanId}

public void ById(int id)
{}

更多信息来自此相关问题Having my Viewmodel appear in namespace dropdown

1 个答案:

答案 0 :(得分:0)

首先,您不应该在ViewModels构造函数中执行查询操作。你不应该做任何昂贵的事情。在类的构造函数中的操作。

其次,ViewModel不应该知道其他ViewModel。因此,您不应该在另一个ViewModel中实例化ViewModel。

我建议采用不同的方法。而不是尝试直接将ID传递给ViewModel,而是通过事件聚合器来完成。 Event Aggregator基本上是一个消息传递系统,用于在ViewModel之间以分离的方式发送消息。

一个ViewModel注册到某个事件,另一个ViewModel发送它的事件,而不知道该事件是否有任何订户或该订户可能是谁。例如PRISM IEventAggregator

您在ViewModel中获取您选择的EventAgregator实例(通过依赖注入或通过服务定位器)并在构造函数中注册您的事件

public class LoanViewModel 
{
    public LoanViewModel()
    {
        IEventAggregator events = ... ; // get via ServiceLocator or via Constructor for DI
        events.GetEvent<CustomerLoadedEvent>().Subscribe(OnCustomerLoaded);
    }

    private void OnCustomerLoaded(Customer customer) 
    {
        int customerId = customer.ID;

        // do your query now
    }
}

public class OtherViewModel 
{
    IEventAggregator events;

    public LoanViewModel()
    {
        this.events; = ... ; // get via ServiceLocator or via Constructor for DI
    }

    // Should be ICommand for WPF binding...assuming SelectedItem is from type Customer
    public void Open() 
    {
        if (SelectedItem != null)
        {
            events.GetEvent<CustomerLoadedEvent>().Publish(SelectedItem);
        }
        this.OnPropertyChanged("Items");
    }
}

这样,您的ViewModel就会完全脱离。

当然,PRISM / CompositeFramework可能对您的需求有点过分。您可以使用其他更简单的事件聚合器,也可以创建自己的事件聚合器。 Api可能不同,想法是一样的