0

カスタム サーバー コントロールを作成しました。基本的に、このカスタム コントロールは、ユーザーがテキスト ボックスに入力するのに役立つテキスト ボックスとブラウザー ボタンを提供します。舞台裏では、コンテキストとユーザーの選択を記述する複雑なデータ構造があります (以下の単純化されたバージョン)。

    [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);
    }

これはほとんど機能しています。内部入力値はコードによって適切に入力され、ポストバックは内部値を適切に再構築しますが、テキストボックスはその値を失います。各ポストバックの後、テキスト ボックスは空のままです。

子コントロールの状態を維持するには、コードで何を修正する必要がありますか?

4

0 に答える 0