首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可观察的DataContracts和双向绑定

可观察的DataContracts和双向绑定
EN

Stack Overflow用户
提问于 2011-09-28 18:18:48
回答 2查看 1.6K关注 0票数 2

在我的WPF应用程序中,我使用WCF服务来获取数据。因此,在某些时候,我有一些“复杂”的对象,它们需要将DataContract作为一个整体传递给WPF应用程序。

当然,现在我需要响应更改,并且我在我的ViewModels上实现了INotifyPropertyChanged,但是由于一些对象实际上是DataContracts,所以我必须重新组合这些对象,以便它们实现INotifyPropertyChanged。

我觉得这里很乱。

我尝试做的是直接在DataContract定义上实现接口,但是我不能正确地对更改做出反应。

例如,如果双向数据绑定TextBox的文本被更改,我的ViewModel应该通过更改相应SQL表中的值(通过WCF服务)来响应它,但由于对象是在WCF端定义的,所以我不能在属性的setter中执行此操作。

现在,我要做的是订阅DataContracts的PropertyChanged事件,并使用反射来了解哪个属性发生了更改,以及它的新值。

但这些对象被保存在ObservableCollection<T>中,这是很多事件,它感觉非常脆弱……例如,如果我在集合中添加/删除一个元素呢?

我这样做(我认为这很糟糕):

代码语言:javascript
复制
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吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-01 21:46:00

好的,经过一段时间的思考后,我现在这样实现了它,但它可能会改变,因为我会在下周一会见一位专家(如果他给我一个更好的想法,我会更新)。

1) WCF服务有一个DataContract,如:

代码语言:javascript
复制
[DataContract]
public class MyWcfData : INotifyPropertyChanged
{
    public MyWcfData()
    {
       MyField = "";
    }

    [DataMember]
    public string MyField;

    [DataMember]
    public string MyFieldModified;
}

注意: INotifyPropertyChanged是以通常的方式实现的,我只是为了可读性而省略了它,因为我在这台计算机上没有我的代码片段。

在服务上调用GetMyData()时,它将返回该类的一个实例,其中只填充了"MyField“。MyFieldModified保留为null。

在我的DAL (所以是客户端)上,接收MyWcfData:

代码语言:javascript
复制
public class MyDAL
{
   //... some init code
   public MyWcfData GetMyWcfData()
   {
      MyWcfData newData = m_WcfService.GetMyData();
      newData.MyFieldModified = newData.MyField;
      return newData;
   }
}

这里的要点是,需要复制数据,以便我可以跟踪更改,并在最后只更新一次属性,即使用户更改了10次(我只是将每次都与原始值进行比较)。但是我不想通过网络发送重复的数据,所以在任何业务对象访问它之前,我在DAL中进行复制。

在我的视图的ViewModel上:

代码语言:javascript
复制
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中,我绑定到TextBox中的MyFieldModified (双向绑定)。

然后,我使用System.Windows.InteractivityTextChanged事件上调用DelegateCommand

当最后一个命令被触发时,我将更改放入队列中(以跟踪更改顺序),并在用户按下Save按钮时将其发送回Wcf服务以实现数据持久化。

注意:我实际上使用了一个定制的ObservableQueue<T>,这样我就可以跟踪更改的数量,并通过绑定相应地启用保存按钮。我会写一篇关于它的博客文章,所以请继续关注;-)

Note2:我放弃了让它立即保存每一个微小的更改,即使在这种情况下它可以工作,因为它不是一个经常使用的功能,并且几乎没有预期的更改;但正如在其他答案中指出的那样,这是一种糟糕的做法。

票数 0
EN

Stack Overflow用户

发布于 2011-09-28 21:35:09

因此,您想要一个通过WCF服务器链接到数据库的实时系统?

如何创建Model对象,该对象的Get/Set方法与数据库交互?

代码语言:javascript
复制
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服务调用异步,这可能会提高性能,尽管如果有多个人可以修改单个对象,则可能需要某种消息传递系统,以便在另一个用户更新属性时向客户端发出MyObject已更改的警报。

客户端上的ViewModel将负责创建模型,而不是WCF服务。

代码语言:javascript
复制
public class LoadObject(int id)
{
    CurrentObject = new MyModel(serviceReference, id);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7581687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档