在我的WPF应用程序中,我使用WCF服务来获取数据。
很自然地,在某些时候我有“复杂”的对象需要将DataContract
作为一个整体传递给WPF应用程序。
当然,我需要响应更改,并在ViewModel上实现INotifyPropertyChanged
,但是由于某些对象实际上是DataContracts,因此我必须重新构造它们,以便它们实现INotifyPropertyChanged。
我觉得它很乱。
我尝试做的是直接在DataContract定义上实现接口,但我无法对更改做出适当的反应。
例如,如果双向数据绑定TextBox
的文本发生了更改,我的ViewModel应该通过更改相应SQL表中的值(通过WCF服务)来对它做出反应,但由于该对象是在WCF端定义的,我不能在财产的设定者那里做到这一点。
我现在所做的是订阅DataContracts的PropertyChanged事件,并使用反射来了解哪些属性已更改及其新值。
但是这些对象是ObservableCollection<T>
,这是很多事件,感觉非常脆弱......例如,如果我从集合中添加/删除元素会怎样?
我这样做(我觉得这很糟糕):
foreach (ImageInfo imgi in (param.Images as ObservableCollection<ImageInfo>))
{
imgi.PropertyChanged += (sender, args) =>
{
object newValue = Tools.GetProperty((sender as ImageInfo), args.PropertyName);
};
}
然后我将它发送回WCF服务。
对此有更优雅的解决方案吗?我应该只在ViewModel上实现INotifyPropertyChanged,而是重新组合DataContracts吗?
谢谢!
答案 0 :(得分:1)
所以你想要一个由WCF服务器链接到数据库的实时系统吗?
如何创建模型对象,其Get / Set方法是进出数据库的?
public class MyModel : INotifyPropertyChanged
{
private IMyModelService service;
public int Id { get; set; }
public MyModel (IMyModelService wcfService, int id)
{
this.Id = id;
this.service = wcfService;
AutoMapper.Map<MyModelDTO, MyModel>(service.GetMyModel(this.Id), this);
}
public int SomeValue
{
get
{
return service.GetSomeValue(this.Id);
}
set
{
service.SetSomeValue(this.Id, value);
RaisePropertyChanged("SomeValue");
}
}
}
您还可以在本地缓存对象属性并使WCF服务调用异步,这可能会提高性能,但如果多个人可以修改单个对象,则可能需要某种消息传递系统来警告客户{当另一个用户更新属性时,{1}}已更改。
客户端上的ViewModel将负责创建Model,而不是WCF服务。
MyObject
答案 1 :(得分:0)
好吧,经过一段时间的思考,我现在就像这样实现它,但它可能会改变,因为我下周一会见专家(如果他给我一个更好的主意,我会更新)。
1)WCF服务有一个DataContract,例如:
[DataContract]
public class MyWcfData : INotifyPropertyChanged
{
public MyWcfData()
{
MyField = "";
}
[DataMember]
public string MyField;
[DataMember]
public string MyFieldModified;
}
注意: INotifyPropertyChanged以通常的方式实现,我只是为了提高可读性而将其删除,因为我在这台计算机上没有我的代码段。
当在服务上调用GetMyData()时,它返回该类的实例,只填充“MyField”。 MyFieldModified留空。
在我的DAL(客户端),收到MyWcfData的地方:
public class MyDAL
{
//... some init code
public MyWcfData GetMyWcfData()
{
MyWcfData newData = m_WcfService.GetMyData();
newData.MyFieldModified = newData.MyField;
return newData;
}
}
这里的要点是数据需要重复,以便我可以跟踪更改,并且最后只更新一次属性,即使用户将其更改了10次(我只是将每次更改为原始值) )。但是我不希望通过网络发送重复数据,所以我会在任何业务对象访问它之前在DAL中进行复制。
在我的观点的ViewModel上:
public class MyViewModel
{
//.. some init code
DelegateCommand<MyWcfData> _GetDataCommand;
public DelegateCommand<MyWcfData> GetDataCommand
{
get
{
if (_GetDataCommand == null)
_GetDataCommand = new DelegateCommand<MyWcfData>(GetData);
return _GetDataCommand;
}
}
public void GetData(MyWcfData param)
{
m_WcfData = m_DAL.GetMyWcfData();
}
}
然后最后但并非最不重要的是,在我的XAML中,我绑定到MyFieldModified
中的TextBox
(双向绑定)。
然后我使用System.Windows.Interactivity
来在DelegateCommand
活动中致电TextChanged
当最后一个命令被触发时,我将更改放入队列(以跟踪更改顺序),并在用户按下“保存”按钮时将其发送回Wcf服务以获得数据持久性。
注意:我实际上使用了自定义的ObservableQueue<T>
,以便我可以跟踪更改的数量,并通过绑定相应地启用保存按钮。我将发表关于它的博客文章,敬请关注; - )
注2:我放弃了让它立即保存每一个微小的变化,即使在这种情况下它会起作用,因为它不是一个很常用的功能,并且预计几乎没有变化;但正如其他答案所指出的那样,这是不好的做法。