问题:我有两个与列表共享服务的视图模型。我的问题是如何设置通知,以便两个视图模型知道此列表何时更改。下面的说明和我在哪里的代码。
我发现这个示例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);
}
}
答案 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)
好的,让我试着说清楚这一点。首先,更改通知并不意味着在视图模型之间传递信息,它旨在通知视图本身视图模型的属性已更改。
视图模型有一些方法可以向视图发出更改通知:
INotifyPropertyChanged
interface INotifyCollectionChanged
interface Changed
(例如,名为MyPropChanged
的属性名为MyProp
的事件说了这么多,一个视图模型仍然可以订阅上述方法生成的事件,如果你真的需要,你当然也可以。
修改强>
检查此link以获取有关上述第3项的说明。