我正在使用RIA服务&amp ;;在Silverlight 4应用程序中使用一些基本的MVVM设计原则。实体。这是基本的方案似乎工作正常:
DataViewModel.cs
public DataViewModel : NotificationObject
private DataDomainContext _dataContext;
public DataViewModel()
{
_dataContext = new DataDomainContext();
if (!DesignerProperties.IsInDesignTool)
{
Data = _dataContext.Data;
dataContext.Load(_dataContext.GetDataQuery(), null, null);
}
}
private IEnumerable<DataEntity> _data;
public IEnumerable<DataEntity> Data // INPC property
{
get { return _data; }
set
{
if (value != _data)
{
_data = value;
PropertyChanged(this, new PropertyChangedEventArgs("Data"));
}
}
}
}
我视图中的DataGrid与DataViewModel.Data单向绑定,DataDomainContext是在为DataEntity对象编译域服务后公开的RIA域上下文。
我想将视图模型与DAL分离。我想要一个DataService类,它将负责向域上下文询问数据:
public DataViewModel : NotificationObject
private DataService _dataService;
public DataViewModel(DataService dataService)
{
_dataService = dataService;
if (!DesignerProperties.IsInDesignTool)
{
Data = _dataService.Data;
_dataService.GetData();
}
}
...
}
然而,我似乎无法做对。这很容易吗?我以前没有设计过带回调的数据服务。我尝试通过INPC在三个类中链接数据属性,但UI中的DataGrid显示为空白。我还想转换为一个新类型DataDto的集合,所以我的表示层没有耦合到后端。我没有运气就试过这样的事情:
DataService.cs
public DataService : INotifyPropertyChanged
{
public DataService()
{
_dataContext = new DataDomainContext();
}
public event PropertyChangedEventHandler PropertyChanged;
public void GetData()
{
DataEntities = _domainContext.Data;
_dataContext.Load(_dataContext.GetDataQuery(), FinishedLoading, null);
}
private void FinishedLoading(...)
{
Data = DataEntities.Select(de => new DataDto(de));
}
public IEnumerable<DataDto> Data { ... } // INPC property, used for binding in ViewModel
public IEnumerable<DataEntity> DataEntities { ... } // INPC property
...
}
我是否在正确的轨道上?我是否从高层次遗漏任何东西,或者我没有正确的细节?
修改
我终于弄明白了。答案包括通过Action&lt;&gt;将回调传递给数据服务/存储库调用。调用的返回类型实际上是无效的,事件args用于传递结果。如果有人有兴趣,我很乐意发布一些有效的代码,只需在评论中留下请求。
答案 0 :(得分:2)
我认为你走在正确的轨道上,但在我看来你的解决方案是不正确的,如果你实际上试图将你的视图模型与数据服务分离。我正在开发一个与此非常相似的应用程序。不同的人对mvvm有不同的看法,这只是我从试错中学到的个人方法(使用visual studio):
首先创建silverlight应用程序项目并将其托管在.web项目中。 silverlight项目将保存视图和视图模型。视图模型应该包含您的模型,而不是您的数据服务!但是,视图模型应该具有数据服务的实例来设置模型。我的数据服务在哪里?我很高兴你问:)。添加另一个项目,即WCF RIA服务类库。这实际上是两个项目,一个ria服务(服务器端)dll和一个相应的silverlight(客户端)dll。您可以将实体框架或其他数据库访问代码添加到服务器端。之后,将域服务添加到服务器端项目。首先构建它(重要),然后转到客户端ria服务dll并使用您的数据服务方法创建一个数据服务类,如下所示:
public void GetData( string filter, Action<LoadOperation<MyEntityType>> callback )
{
var q = from e in _context.GetDataQuery()
where e.SomeField.Contains(filter)
select e;
_context.Load(q, LoadBehavior.RefreshCurrent, callback, null);
}
您的数据服务不应实现Inotifyproperty已更改,因为这是视图模型角色! 在您的silverlight项目中引用ria服务客户端dll,并在Web主机项目中引用ria服务服务器端dll 视图模型应该像这样调用这个数据服务:
IEnumerable<MyEnityType> Model {get;set;}
//NOTE: add notify property changed in setter!
private void GetData()
{
_myDataService.GetData( _filter, loadOperation =>
{
if ( loadOperation.HasError )
HandleError(loadOperation.Error);
Model = loadOperation.Entities;
} );
}
如果您真的想要解耦数据服务,可以更进一步,实现数据服务的接口。采用这种方法可以重新使用您的数据服务(如果您需要桌面应用程序或手机应用程序),我希望这有助于清理事情!