На первый взгляд, я бы проверил две вещи. Во-первых, убедитесь, что вы реализуете IPostBackDataHandler
. для этого необходимо реализовать два метода: LoadPostData
и RaisePostDataChangedEvent
. На мой взгляд, первый, вероятно, является источником вашей проблемы.
Обработка обратной передачи вручную
LoadPostData
принимает строку postDataKey
и NameValueCollection
postCollection
и возвращает bool
, указывающее, изменилось ли значение в результате обратной передачи. Вам не нужно реализовывать это так, как изначально предполагалось .Net, например, я создал элемент управления, содержащий несколько переключателей (которые по причинам, которые здесь не важны, не могут быть просто RadioButtonList
control), поэтому убедился, что все они названы свойством string GroupName
, и проверил postCollection
для этого GroupName
:
public bool LoadPostData(string postDataKey,
System.Collections.Specialized.NameValueCollection postCollection)
{
bool oldValue = _isChecked;
postCollection = HttpContext.Current.Request.Form; // See note below
_isChecked = (postCollection[this.GroupName] == this.Text);
return oldValue == _isChecked;
}
Вы заметите, что я здесь переопределяю postCollection
; это потому, что postCollection
содержит только подмножество HttpRequest.Form
, соответствующее тому, что, по мнению ASP.Net, должно заботить ваш элемент управления. Поскольку вы также создаете здесь составной элемент управления, вы, вероятно, захотите сделать то же самое.
Не волнуйтесь, если это не сработает с первого раза; стоит пройтись по тому, что передается в этот метод в режиме отладки (или выводить данные в HttpContext.Trace
, что мне часто кажется проще), чтобы понять, почему ваш код не совсем то, что вам нужно.
Небольшая оговорка
И последнее: LoadPostData
вызывается только в том случае, если опубликованная форма содержит поле с именем, которое соответствует UniqueID
вашего элемента управления. Поскольку ваш элемент управления является составным элементом управления, вы можете немного изменить его, например:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
writer.WriteBeginTag("input");
writer.WriteAttribute("type", "hidden");
writer.WriteAttribute("name", this.UniqueID);
writer.WriteAttribute("value", "post");
writer.Write(" />");
}
Это грязный прием, но он сработает; o)
Обработка состояния просмотра вручную
Если обработка обратной передачи вручную не решает вашу проблему, возможно, вам нужно вмешаться в состояние просмотра вашего элемента управления. Не волнуйтесь, это далеко не так страшно, как кажется, если следовать нескольким простым правилам.
Чтобы обрабатывать состояние просмотра вручную, вам просто нужно переопределить два метода, которые, очевидно, называются LoadViewState
и SaveViewState
. Первый принимает object
состояния просмотра для надувания, а другой возвращает ту же object
структуру. Если вы заставляете ваше SaveViewState
переопределение возвращать что-то, содержащее структуру, необходимую для сохранения всех важных свойств, которые необходимо сохранить, тогда вы просто раздуваете это снова в своем LoadViewState
методе.
Вот здесь и проявляется первая хитрость. Есть определенные типы данных, которые вы должны использовать для сохранения состояния просмотра, и вы никогда не должны использовать какой-либо другой тип (потому что другие типы хранятся очень неэффективно). Типы, которые, вероятно, будут вам наиболее полезны: System.Web.UI.Pair
< / a>, System.Web.UI.Triplet
и наши старые друзья System.Collections.ArrayList
и _ 30_. Пары и тройки просто хранят два или три значения типа object
; ArrayLists - это фактически List<object>
.
Я предполагаю, что в ваших обстоятельствах вы, вероятно, захотите сохранить либо (1) ArrayList логических флагов, сохраняя «проверяемость» ваших радиокнопок, либо (2) ArrayList строк или целых чисел, сохраняя идентификаторы или индекс проверенные радиокнопки.
В элементе управления, о котором я упоминал ранее, мне просто нужно было сохранить проверку и свойство Text
, поэтому мои методы LoadViewState
и SaveViewState
выглядели так:
protected override void LoadViewState(object savedState)
{
Pair state = savedState as Pair;
if (state != null)
{
_isChecked = state.First as Nullable<bool> ?? false;
this.Text = state.Second as string;
}
}
protected override object SaveViewState()
{
return new Pair(_isChecked, this.Text);
}
Опять же, если это не сработает с первого раза, вы почти наверняка захотите выполнить код или добавить что-то в трассировку. Важно отметить, что вы, вероятно, хотите избежать выдачи исключений из этих методов, если ваше состояние просмотра повреждено или отсутствует или что-то в этом роде.
Дополнительная литература о viewstate
Есть пара очень полезных статей, на которые я делаю закладки, когда возюсь с viewstate. Первый объясняет, почему вы должны хранить только определенные типы в состоянии просмотра (например, с использованием ArrayList
и Hashtable
, а не List<T>
и Dictionary<TKey, TValue>
), а второй является хорошим подробным объяснением того, как на самом деле работает весь этот материал состояния просмотра.
- Не позволяйте BinaryFormatter добраться до этого!
- Истинное понимание ViewState
Надеюсь, все это поможет решить вашу проблему.
person
Owen Blacker
schedule
05.10.2010