2008-12-12 21 views
8

描述了一個例子here。但作者顯然忘記了包含下載的代碼。如何創建一個通用StateManagedCollection?

另一示例顯示爲here。但是,這個不太合適(如評論中所述)。

你如何正確地做到這一點?

+0

這是一個[更新的鏈接到第二個例子](http://blog.spontaneouspublicity.com/child-collections-in-asp-net-custom-controls) – 2012-07-05 18:13:47

+0

謝謝你更新。 – Larsenal 2012-07-05 19:09:55

回答

3

DanHerbert明白了。該死,我也在這上面花了幾個小時!在試圖回答這個問題的過程中,我想出了一個簡化的通用StateManagedCollection,它從Framework的內置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 
    } 
} 
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); 
} 

示例站點中的代碼相當不錯。它實現了它應該擁有的所有接口,並且做得非常好。儘管在抽象代碼中包含了所有需要的代碼,但它們分開的地方並不重要,因爲在需要的地方沒有引用這些接口。

正在使用的集合類對它們沒有任何「特殊」,除了實現一些接口。框架不會自動調用這些方法。框架然而調用我上面寫的重寫的方法,你需要實現,以便您的控件保存集合中的元素。只要你給他們打電話,一切都會奏效。

0

我已經使用所提供的解決方案上面的代碼是確定,但我是越來越例外 - 「StackOverflow的」酷:)問題是在aspx頁面添加幾個子項目重複性,並切換到設計視圖Visual Studio的設計視圖(Visual Studio只是重新啓動,沒人知道發生了什麼......)。

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

    } 

所以,我想我理解了它只是改變了上述方法的這樣實施:

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

    } 

希望這會幫助別人像我一樣:)只是不丟失幾個小時得到它與設計師的工作VS