多个视图模型与通知共享服务

时间:2015-03-25 14:29:05

标签: c# wpf mvvm viewmodel mvvm-light

问题:我有两个与列表共享服务的视图模型。我的问题是如何设置通知,以便两个视图模型知道此列表何时更改。下面的说明和我在哪里的代码。

我发现这个示例HERE看起来适合我尝试做的事情,但我对如何在我的视图模型中通知我的服务更改有疑问。我会添加一些我嘲笑的代码,看看我是否在正确的轨道上。我正在使用WPF / MVVM Light。

第一部分是具有接口的服务,该接口将具有数据列表,在此示例中,我使用字符串列表。我希望两个视图模型中的属性都可以访问此数据列表,并在更改时收到通知。我认为扔我的是IOC接口到我的视图模型中。我越来越了解为什么这样做很好,但我仍然在思考它并且我不确定如何在服务中更改列表时设置通知。如果没有注入我的服务,我可能已经设置了我的viewmodel属性将访问get / set的事件或属性,但是注入我的服务不会暴露我的公共字段,只是方法。这对我来说是新的,所以很可能我没有正确地理解这一点或遗漏了什么。

我在服务中使用了List而不是基于某些阅读的ObservableCollection我已经在这里使用ObservableCollection做了警告。谢谢你的帮助。

public class MyService : IMyService
{
    private List<string> myList = new List<string>();

    public List<string> getMyList()
    {
        return this.myList;
    }
    public void setMyList(List<string> value)
    {
        this.myList = value;
    }
    public void addValue(string value)
    {
        this.myList.Add(value);
    }
    public void insertValue(int index, string value)
    {
        this.myList.Insert(index, value);
    }
}

public class MyViewModelOne : ViewModelBase
{
    private readonly IMyService myService;

    public MyViewModelOne(IMyService myService)
    {
        this.myService = myService;
    }

    public List<string> MyProperty // control item source will bind to this
    {
        get
        {
            return this.myService.getSource();
        }
    }
    public void setSomeValue(value)
    {
        this.myService.addValue(value);
    }
}

public class MyViewModelTwo : ViewModelBase
{
    private readonly IMyService myService;

    public MyViewModelTwo(IMyService myService)
    {
        this.myService = myService;
    }

    public List<string> MyProperty // control item source will bind to this
    {
        get
        {
            return this.myService.getSource();
        }
    }
    public void setSomeValue(value)
    {
        this.myService.addValue(value);
    }
}

3 个答案:

答案 0 :(得分:2)

根据我对您的问题的理解,您实际需要的是您的服务级别的INotifyPropertyChanged实现以及我的列表列表是从服务注入的ObservableCollection。

现在,如果有通知更改,它将直接在服务上,因此没有明确的处理需求。

您的绑定可能看起来像"{Binding MyService.MyProperty}"

答案 1 :(得分:2)

我使用了两种不同的方式,我使用了第一个示例,因为我认为在代码中更容易理解。

这是因为我在我的主视图中有一个控件,其中相关的代码正在增长,我意识到我想在一个单独的视图中使用相同的控件/行为,这些视图将使用相同的数据/控件用于不同的目的。 我不想在两个地方复制这个控件/模板/代码,所以我把它变成了一个用户控件。然后我将用户控件嵌套在我的视图中。用户控件拥有自己的VM。主视图使用新数据更新服务,嵌套控件侦听事件以了解何时有新数据。

MVVM思维还是一个新手,所以请随意指出这些例子中的任何一个问题。

使用带有eventhandler的服务的示例。

public interface IMyInterface
{   
    event EventHandler OnSomeEvent;
    void addSomeData(string value);
    void getSomeData();
}

public class MyInterface: IMyInterface
{
    public event EventHandler OnSomeEvent = delegate { };  

    public void addSomeData(string value)
    {
        // do stuff
        OnSomeEvent();
    }
    public string getSomeData()
    {
        return "some data";
    }
}

// Main ViewModel
public class ViewModelOne : ViewModelBase
{
    IMyInterface myInterface;
    public NotifyViewModel(IMyInterface myInterface)
    {
        this.myInterface = myInterface;
        this.myInterface.OnItemSourceChanged += myInterface_OnSomeEvent;
    }

    void testEvent()
    {
        this.myInterface.addSomeData("test data");
    }
}

// My nested user control
public class ViewModelTwo : ViewModelBase
{
    IMyInterface myInterface;
    public NotifyViewModel(IMyInterface myInterface)
    {
        this.myInterface = myInterface;
        this.myInterface.OnItemSourceChanged += myInterface_OnSomeEvent;
    }

    void myInterface_OnSomeEvent(object sender, System.EventArgs e)
    {
        // do stuff
    }
}

使用MVVM Light Messaging的示例

public class EventDataSource
{
    public string MyItemSource { get; set; }
    public EventDataSource()
    {
        MyItemSource = string.Empty;
    }

}

// Message class
public class MyDataSourceMessage : MessageBase
{
    public EventDataSource MyItemSource { get; set; }
    public MyDataSourceMessage(EventDataSource myItemSource)
    {
        MyItemSource = myItemSource;
    }
}

// Main ViewModel
public class ViewModelOne : ViewModelBase
{
    public NotifyViewModel() {}

    void testMessage()
    {
        EventDataSource msg = new EventDataSource() { MyItemSource = "magic message!"};
        Messenger.Default.Send(new MyDataSourceMessage(msg as EventDataSource));
    }
}

// My nested user control
public class ViewModelTwo : ViewModelBase
{

    public NotifyViewModel()
    {
        Messenger.Default.Register<MyDataSourceMessage>(this, (action) => ReceiveMessage(action));
    }

    private ObservableCollection<string> myProperty = new ObservableCollection<string>();
    public ObservableCollection<string> MyProperty
    {
        get { return myProperty; }
        set
        {
            myProperty: = value;
            RaisePropertyChanged(() => MyProperty);
        }
    }
    void ReceiveMessage(MyDataSourceMessage action)
    {
        // do something with the data
        MyProperty.Add(action.DGItemSource.ItemSource);
    }
}

答案 2 :(得分:1)

好的,让我试着说清楚这一点。首先,更改通知并不意味着在视图模型之间传递信息,它旨在通知视图本身视图模型的属性已更改。

视图模型有一些方法可以向视图发出更改通知:

  1. INotifyPropertyChanged interface
  2. INotifyCollectionChanged interface
  3. 自定义事件,其属性名称后缀为Changed(例如,名为MyPropChanged的属性名为MyProp的事件
  4. 说了这么多,一个视图模型仍然可以订阅上述方法生成的事件,如果你真的需要,你当然也可以。

    修改

    检查此link以获取有关上述第3项的说明。