2008-12-12 12 views
8

Se describe un ejemplo here. Pero el autor aparentemente olvidó incluir el código para descargar.Cómo crear una genérica StateManagedCollection?

Se muestra otro ejemplo here. Sin embargo, este no funciona del todo (como se describe en los comentarios).

¿Cómo se hace esto correctamente?

+0

Aquí hay un [enlace actualizado al segundo ejemplo] (http://blog.spontaneouspublicity.com/child-collections-in-asp-net-custom-controls) –

+0

Gracias por la actualización. – Larsenal

Respuesta

3

DanHerbert lo consiguió. ¡Maldición, pasé horas en esto también! En el proceso de tratar de responder a esta pregunta, se me ocurrió una StateManagedCollection genérica simplificada que hereda de StateManagedCollection incorporado en el marco de trabajo, basada en la versión here. Quizás lo encuentres útil. El código fuente completo de mi proyecto de muestra está disponible 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 
    } 
} 
+0

Opción difícil para recompensa de recompensa, pero el código fuente completo es muy útil. Gracias. – Larsenal

+0

No está implementando IEnumerable .GetEnumerator(). Si usa .NET 3.5, puede reemplazar ese lanzamiento con lo siguiente: ((IEnumerable ) this) .Cast () .GetEnumerator(); –

+0

¿Podría decirme dónde puedo descargar el código fuente de muestra? Porque el enlace que me ha proporcionado me proporciona un mensaje de error. –

4

El second example you found casi funciona, solo falta un poco. Todo lo que se necesitaba eran 2 métodos en el control principal.

Agregue este código al archivo AppointmentControl.cs y funcionará.

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

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

El código en el sitio de ejemplo era bastante decente. Implementó todas las interfaces que debería tener e hizo un trabajo bastante bueno. Donde se derrumbó fue que, a pesar de tener todo el código que necesitaba en los bits abstractos, eso no importaba porque las interfaces no estaban referenciadas en los lugares donde debían estar.

Las clases de colección utilizadas no tenían nada "especial" sobre ellas, aparte de la implementación de algunas interfaces. El marco no llamará automáticamente a estos métodos. El marco será, pero llame a los métodos reemplazados que escribí anteriormente, que debe implementar para que su control pueda guardar los elementos en la colección. Mientras los llames, todo funcionará.

0

he utilizado el código por encima de la solución aportada está bien, pero que estaba recibiendo una excepción - "stackoverflow" fresco :) el problema es reproducible mediante la adición de unos pocos elementos secundarios de la página aspx y cambiar a la vista Diseño de Vista de diseño de Visual Studio (Visual Studio solo reinicia y nadie sabe qué está pasando ...).

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

    } 

tanto, creo que lo he descubierto simplemente cambiar la implementación del método anterior como esto:

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

    } 

Esperamos que esto ayude a alguien más como yo :) simplemente no perder unas horas a hazlo funcionar con el diseñador de VS

Cuestiones relacionadas