




второй пример, который вы нашли почти работает, просто немного не хватает. Все, что требовалось, это 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);
}
Код в примере сайта был довольно приличным. Он реализовал все интерфейсы, которые должен был иметь, и проделал довольно хорошую работу. Он развалился в том, что, несмотря на наличие всего необходимого кода в абстрактных битах, это не имело значения, потому что на интерфейсы не ссылались в тех местах, где они должны были быть.
В используемых классах коллекций не было ничего «особенного», кроме реализации нескольких интерфейсов. Платформа не будет автоматически вызывать эти методы. Однако структура будут вызывает переопределенные методы, которые я написал выше, которые вам необходимо реализовать, чтобы ваш элемент управления сохранял элементы в коллекции. Пока вы им звоните, все будет работать.
Дэн Херберт понял. Черт, я тоже потратил на это часы! Пытаясь ответить на этот вопрос, я придумал упрощенную общую коллекцию StateManagedCollection, которая наследуется от встроенной в фреймворк StateManagedCollection на основе версии здесь. Может быть, тебе это пригодится. Доступен полный исходный код моего демонстрационного проекта здесь.
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
}
}
Сложный выбор для награды за награду, но полный исходный код очень полезен. Спасибо.
Вы не реализуете IEnumerable <T> .GetEnumerator (). Если вы используете .NET 3.5, вы можете заменить этот бросок следующим: ((IEnumerable <T>) this) .Cast <T> () .GetEnumerator ();
Подскажите, пожалуйста, где я могу скачать образец исходного кода? Coz 'ссылка, которую вы дали, дает мне сообщение об ошибке.
@DaveVandenEynde: то, что вы предложили, не сработает, потому что Cast <T> () имеет специальную оптимизацию: он проверяет, реализует ли источник IEnumerable <T>. Если это правда, он просто вернет источник. Здесь это приведет к вызову IEnumerable <T> .GetEnumerator () снова и снова и, в конце концов, вызовет переполнение стека ...
также: вызов SetDirty () в методе StateManagedCollection <T> .Add () не подходит, потому что методы StateManagedCollection уже позаботятся об этом. Если вы это сделаете, такие вещи, как восстановление некоторых свойств, управляемых viewstate, не будут работать должным образом.
Я использовал приведенный выше код, предоставленное решение в порядке, но я получал исключение - "StackOverflow" круто :) Проблема воспроизводится путем добавления нескольких дочерних элементов на страницу aspx и переключения в режим дизайна для просмотра дизайна Visual Studio (Visual Студия просто перезапускается, и никто не знает, что происходит ....).
IEnumerator IEnumerable.GetEnumerator()
{
return ((IList)this).GetEnumerator();
}
Итак, я думаю, я понял, что просто измените реализацию вышеуказанного метода следующим образом:
IEnumerator IEnumerable.GetEnumerator()
{
// return ((IList)this).GetEnumerator();
return this.GetEnumerator();
}
Надеюсь, это поможет кому-то вроде меня :) просто не терять несколько часов, чтобы заставить его работать с дизайнером VS
Вот обновлена ссылка на 2-й пример