C# “可观察收集”;“收藏已更改”;在OutProc会话状态下未触发

C# “可观察收集”;“收藏已更改”;在OutProc会话状态下未触发,c#,asp.net,serialization,C#,Asp.net,Serialization,我正在asp.net应用程序中使用ObservableCollection,通过使用“CollectionChanged”事件,我能够获得添加/删除的值。为此,我将对象存储在session(InProc)中,这里的一切都很好 现在的问题是,当我将会话更改为outproc(DB)时,Collection\u CollectionChanged stopped firing(按钮2\u单击)。我认为必须对序列化做些什么。感谢您在这方面的帮助 示例的用法: 首先单击按钮1,然后单击按钮2,按钮1和按钮

我正在asp.net应用程序中使用ObservableCollection,通过使用“CollectionChanged”事件,我能够获得添加/删除的值。为此,我将对象存储在session(InProc)中,这里的一切都很好

现在的问题是,当我将会话更改为outproc(DB)时,Collection\u CollectionChanged stopped firing(按钮2\u单击)。我认为必须对序列化做些什么。感谢您在这方面的帮助

示例的用法: 首先单击按钮1,然后单击按钮2,按钮1和按钮2事件都在aspx代码中

  [Serializable]
    public class School
    {
        public School()
        {
            studentList = new ObservableCollection<Student>();            
            studentList.CollectionChanged += Collection_CollectionChanged;
        }
        public string SchoolName { get; set;}
        public ObservableCollection<Student> studentList { get; set; }
        public void Collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
           if (e.Action == NotifyCollectionChangedAction.Add)
            {
                var result= "add";
            }
           else if (e.Action == NotifyCollectionChangedAction.Remove)
           {
               var result=  "del";
           }
        }
    }

    [Serializable]
    public class Student
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    //Code in .aspx.cs Page
    protected void Button1_Click(object sender, EventArgs e)
    {
        School school = new School();
        school.SchoolName = "Benie";
        school.studentList.Add(new Student() { FirstName = "a", LastName = "a1" });
        school.studentList.Add(new Student() { FirstName = "b", LastName = "b1" });
        Session["school"] = school;
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        School school = Session["school"] as School;
        //Not working in Out Proc session, Working in InProc session
        school.studentList.RemoveAt(1);
    }
[可序列化]
公立学校
{
公立学校()
{
studentList=新的ObservableCollection();
studentList.CollectionChanged+=集合\u CollectionChanged;
}
公共字符串SchoolName{get;set;}
公共可观察集合学生列表{get;set;}
public void Collection\u CollectionChanged(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if(e.Action==NotifyCollectionChangedAction.Add)
{
var result=“添加”;
}
else if(e.Action==NotifyCollectionChangedAction.Remove)
{
var result=“del”;
}
}
}
[可序列化]
公立班学生
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
//.aspx.cs页面中的代码
受保护的无效按钮1\u单击(对象发送者,事件参数e)
{
学校=新学校();
school.SchoolName=“Benie”;
school.studentList.Add(newstudent(){FirstName=“a”,LastName=“a1”});
school.studentList.Add(newstudent(){FirstName=“b”,LastName=“b1”});
课时[“学校”]=学校;
}
受保护的无效按钮2\u单击(对象发送者,事件参数e)
{
学校=课时[“学校”]作为学校;
//在进程外会话中不工作,在进程内会话中工作
学校。学生名单。删除(1);
}

我怀疑CollectionChanged事件没有钩住,因为该对象是通过序列化创建的(我认为奇怪但可能),或者序列化后按钮1\u单击没有钩住(可能性更高,因为您没有在构造函数中执行此操作,但我阅读了您的其他问题)


要解决这个问题,您可以尝试为学校类实现ISerializable(不要忘记构造函数),并在序列化构造函数中钩住事件。

我同意问题肯定是序列化,特别是学生对象被ObservableCollection包装的事实。如果您想继续使用这种方法,您可以自己实现自定义序列化


Kent Bogart发表了一篇关于这个确切场景以及如何在ObservableCollections上实现自定义序列化的文章

问题是,
CollectionChanged
事件没有标记为“非序列化”。因此,反序列化后,
集合更改
null
。弗洛姆的解决方案

[可序列化]
公共类SObservableCollection:ObservableCollection,
InotifyProperty已更改
{
[字段:非序列化]
公共覆盖事件NotifyCollectionChangedEventHandler CollectionChanged;
[字段:非序列化]
私有财产变更管理人(u财产变更管理人);;
事件属性ChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
添加
{
_propertyChangedEventHandler=委托。将(\u propertyChangedEventHandler,value)合并为propertyChangedEventHandler;
}
去除
{
_propertyChangedEventHandler=委托。将(\u propertyChangedEventHandler,value)作为propertyChangedEventHandler删除;
}
}
CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler处理程序=CollectionChanged;
if(处理程序!=null)
{
处理者(本,e);
}
}
受保护的重写无效OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler处理程序=\u PropertyChangedEventHandler;
if(处理程序!=null)
{
处理者(本,e);
}
}
}

您的学生类中有按钮单击处理程序吗?@Henk Holterman:在aspx页面中,这两种方法的代码不同。在
按钮2\u单击
,学生列表中是否确实有要删除的项目?@seldon:Yes按钮1将第一次单击,因此2个项目将添加到列表中,然后单击按钮2删除其中一个添加的项目。
[Serializable]
public class SObservableCollection<T> : ObservableCollection<T>, 
    INotifyPropertyChanged
{
    [field:NonSerialized]
    public override event NotifyCollectionChangedEventHandler CollectionChanged;

    [field: NonSerialized]
    private PropertyChangedEventHandler _propertyChangedEventHandler;

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add
        {
            _propertyChangedEventHandler = Delegate.Combine(_propertyChangedEventHandler, value) as PropertyChangedEventHandler;
        }
        remove
        {
            _propertyChangedEventHandler = Delegate.Remove(_propertyChangedEventHandler, value) as PropertyChangedEventHandler;
        }
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        NotifyCollectionChangedEventHandler handler = CollectionChanged;

        if (handler != null)
        {
            handler(this, e);
        }
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = _propertyChangedEventHandler;

        if (handler != null)
        {
            handler(this, e);
        }
    }
}