【问题标题】:ObservableCollection and CollectionChanged event as WCF datacontractObservableCollection 和 CollectionChanged 事件作为 WCF 数据契约
【发布时间】:2011-12-23 05:41:37
【问题描述】:

我将 DataContract 与 ObservableCollection 一起使用:

[DataContract(Namespace = Terms.MyNamespace)]
public class MyContract 
{
internal MyContract ()
        {
            List = new ObservableCollection<string>();
        }
[DataMember]
private ObservableCollection<string> list;

[XmlArray("list")]
        public ObservableCollection<string> List
        {
            get
            {
                return list;
            }
            set
            {
                list = value;
                list.CollectionChanged += (s, e) =>
                    { 
                        Console.WriteLine("It is never happens!! Why?"); 
                    };
            }
        }
...

所以,当我像这样处理我的收藏时。

MyContract contract = new MyContract();
contract.List.Add("some");

已添加项目,但未触发 CollectionChanged 事件。

为什么?

【问题讨论】:

  • WCF 数据合约应该包含任何逻辑/代码,因为该代码不能通过从服务器到客户端和返回的通信链路进行序列化。 WCF 是一个消息传递系统——所有从客户端到服务器再返回的都是序列化的 XML 消息,这些消息不能包含行为/逻辑/代码。
  • 好的,在这种情况下可以做些什么吗?当客户端集合发生更改时,我需要标记我的合同(例如将布尔数据成员字段设置为 true)。无法在代码中隐式设置此字段...
  • 客户端上的那些数据契约将是部分类——您可以扩展这些类来处理更改检测以及数据契约内的属性设置。您只需要在客户端上使用该标志吗?或者您是否需要在某个时候将其传输回服务器??
  • 我需要将此标志传输回服务器。问题是当我延长合同时,它对 Observable 集合不起作用。因此,如果我在属性的 set 部分设置我的标志 - 它工作正常,但如果我使用 obserablese 集合 throw Add、Insert 和 Remove 方法,我无法检测到该集合已更改。因为 OnCollectionChanged 事件不起作用。

标签: c# .net wcf observablecollection inotifycollectionchanged


【解决方案1】:

那是因为您在序列化list 时没有序列化List。因此,在反序列化过程中,它不会调用列表的 setter,因此不会订阅事件。在您的情况下,您可以简单地将List 标记为DataMemberAttribute 而不是list,例如:

[DataContract]
public class MyContract
{
    private ObservableCollection<string> list;

    internal MyContract()
    {
        List = new ObservableCollection<string>();
    }

    [DataMember]
    public ObservableCollection<string> List
    {
        get
        {
            return list;
        }
        private set
        {
            list = value;
            list.CollectionChanged += 
               (s, e) => 
                   Console.WriteLine("It is never happens!! Why? - Are you sure?!");
        }
    }
}

用法:

var obj = new MyContract();

var serializer = new DataContractSerializer(typeof(MyContract));

using (var ms = new MemoryStream())
{
    serializer.WriteObject(ms, obj);

    ms.Seek(0, SeekOrigin.Begin);

    var result = serializer.ReadObject(ms) as MyContract;

    result.List.Add("a");
}

在这种情况下,事件将触发。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-06
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    相关资源
    最近更新 更多