カスタム サーバー コントロールを作成しました。基本的に、このカスタム コントロールは、ユーザーがテキスト ボックスに入力するのに役立つテキスト ボックスとブラウザー ボタンを提供します。舞台裏では、コンテキストとユーザーの選択を記述する複雑なデータ構造があります (以下の単純化されたバージョン)。
[Serializable]
public class PickerValue
{
public PickerType Type { get; set; }
public string TargetUrl { get; set; }
public static PickerValue Default()
{
return new PickerValue
{
TargetUrl = "/",
Type = PickerType.Value1
};
}
}
次に、自分のコントロールで、この型のプロパティを宣言し、ビュー ステートを維持します。
public PickerValue Value
{
get
{
var obj = ViewState["Value"];
return (PickerValue)(obj != null ? obj : ViewState["Value"] = PickerValue.Default());
}
set
{
ViewState["Value"] = value;
}
}
私のカスタム コントロールはそのような値を保持し、ポストバック イベントを発生させる必要があるためIPostBackDataHandler
、この値の JSON 表現 (newtonsoft.json を使用) を変換して読み取るようにコントロールを実装しました (これは JavaScript コードで使用されます)。
public event EventHandler ValueChanged;
protected virtual void OnValueChanged(EventArgs e)
{
if (ValueChanged != null) ValueChanged(this, e);
}
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
var presentValue = JsonConvert.SerializeObject(Value);
var postedValue = postCollection[postDataKey];
if (!string.IsNullOrEmpty(presentValue) && !presentValue.Equals(postedValue))
{
Value = JsonConvert.DeserializeObject<PickerValue>(postedValue);
return true;
}
else
{
return false;
}
}
public void RaisePostDataChangedEvent()
{
OnValueChanged(EventArgs.Empty);
}
また、コントロールのレンダリングをカスタマイズし<input type='hidden'>
て、コントロールの値に関連する適切なものを生成します。
protected override void RenderContents(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_data");
writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
writer.AddAttribute(HtmlTextWriterAttribute.Value, JsonConvert.SerializeObject(Value));
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
RenderChildren(writer);
}
最後に、(私が推測する) 適切な使用方法を使用して、テキスト ボックスと参照ボタンを生成しますCreateChildControls
。
protected TextBox txtTargetUrl;
protected Button btnBrowse;
protected override void CreateChildControls()
{
this.txtTargetUrl = new TextBox();
this.Controls.Add(this.txtTargetUrl);
this.btnBrowse = new Button
{
Text = BrowseButtonText
};
this.Controls.Add(this.btnBrowse);
}
これはほとんど機能しています。内部入力値はコードによって適切に入力され、ポストバックは内部値を適切に再構築しますが、テキストボックスはその値を失います。各ポストバックの後、テキスト ボックスは空のままです。
子コントロールの状態を維持するには、コードで何を修正する必要がありますか?