如何创建Generic StateManagedCollection?

时间:2008-12-12 22:17:48

标签: asp.net viewstate

一个例子描述为 here 。但作者显然忘记了下载代码。

另一个示例显示为 here 。但是,这个不太有效(如评论中所述)。

你是如何正确地做到这一点的?

3 个答案:

答案 0 :(得分:4)

second example you found 几乎可以正常工作,它只是遗漏了一点点。所需要的只是主控制中的2种方法。

将此代码添加到AppointmentControl.cs文件中,它将起作用。

protected override object SaveViewState()
{
    if (appointments != null)
        return appointments.SaveViewState();
    return null;
}

protected override void LoadViewState(object savedState)
{
    appointments = new AppointmentCollection();
    appointments.LoadViewState(savedState);
}

示例网站中的代码相当不错。它实现了它应该拥有的所有接口并且做得非常好。它崩溃的地方是,尽管在抽象位中需要所有代码,但这并不重要,因为接口没有在它们需要的位置引用。

除了实现一些接口之外,正在使用的集合类对它们没有什么“特殊”。框架不会自动调用这些方法。然而,框架 会调用我上面编写的重写方法,您需要实现这些方法,以便您的控件将元素保存在集合中。只要你打电话给他们,一切都会奏效。

答案 1 :(得分:3)

DanHerbert得到了它。 Darn,我也花了几个小时!在尝试回答这个问题的过程中,我提出了一个简化的通用StateManagedCollection,它继承自框架的内置StateManagedCollection,基于版本here。也许你会发现它很有用。我的示例项目的完整源代码可用here

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Security.Permissions;
using System.Web;
using System.Collections.Generic;
using System.Web.UI;

namespace Web
{
    public abstract class StateManagedCollection<T> : StateManagedCollection, IList<T>, ICollection<T>, IEnumerable<T>
        where T : class, IStateManagedItem, new()
    {

        protected override object CreateKnownType(int index)
        {
            return Activator.CreateInstance<T>();
        }

        protected override Type[] GetKnownTypes()
        {
            return new Type[] { typeof(T) };
        }

        protected override void SetDirtyObject(object o)
        {
            ((IStateManagedItem)o).SetDirty();
        }

        #region IList<T> Members

        public int IndexOf(T item)
        {
            return ((IList)this).IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            ((IList)this).Insert(index, item);
            if (((IStateManager)this).IsTrackingViewState)
            {
                this.SetDirty();
            }
        }

        public void RemoveAt(int index)
        {
            ((IList)this).RemoveAt(index);
            if (((IStateManager)this).IsTrackingViewState)
            {
                this.SetDirty();
            }
        }

        public T this[int index]
        {
            get { return (T)this[index]; }
            set { this[index] = value; }
        }

        #endregion

        #region ICollection<T> Members

        public void Add(T item)
        {
            ((IList)this).Add(item);
            this.SetDirty();
        }

        public bool Contains(T item)
        {
            return ((IList)this).Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            ((IList)this).CopyTo(array, arrayIndex);
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(T item)
        {
            if (((IList)this).Contains(item))
            {
                ((IList)this).Remove(item);
                return true;
            }
            return false;
        }

        #endregion


        #region IEnumerable<T> Members

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IList)this).GetEnumerator();

        }

        #endregion
    }
}

答案 2 :(得分:0)

我已经使用了上面提供的解决方案上面的代码,但是我得到了异常 - “StackOverflow”酷:)这个问题可以通过在aspx页面中添加一些子项来切换到设计视图来设计Visual视图工作室(Visual Studio刚刚重启,没有人知道发生了什么......)。

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IList)this).GetEnumerator();

    }

所以,我想我只想改变上面这个方法的实现:

    IEnumerator IEnumerable.GetEnumerator()
    {
        // return ((IList)this).GetEnumerator();
        return this.GetEnumerator();

    } 

希望这会帮助像我这样的其他人:)只是不要放松几个小时让它与VS的设计师合作