摘要:我有一个动态添加到页面的Web控件。该控件有一个HiddenField子控件。我将控件的ClientID传递给将值设置为字符串(将json转换为字符串)的jquery小部件。将表单发布回服务器后,HiddenField的值为空白字符串。我的值在Request.Form [UniqueID]对象中。该值将其返回给服务器。问题是,当我需要该值而无需修改大量旧代码时,就无法访​​问Request对象。

奇怪的是,selectmany控件是我遇到的一个问题,但它继承自可以正常工作的SelectOne。我认为我在selectmany类中做错了,因为即使我尝试将值推入SelectOneHiddenValue也不起作用,但是当SelectOne使用它时它可以正常工作。

SelectOne:

[ToolboxData("<{0}:SelectOne runat=server></{0}:SelectOne>")]
public class SelectOne : Panel, IControl,ISelectOne
{
    #region structure

    private readonly Panel _selectOneTextboxContainer = new Panel();
    protected readonly TextBox SelectOneTextbox = new TextBox();
    protected readonly HiddenField SelectOneHiddenValue = new HiddenField();
    private readonly Panel _selectOneDropdownImageContainer = new Panel();
    private readonly Image _selectOneDropDownImage = new Image();

    #endregion

    private readonly IList<LookupItem> _selectedItems = new List<LookupItem>();

    #region properties
    public IList<LookupItem> SelectedItems { get { return _selectedItems; } }

    public bool MultiSelect { get; set; }
    public DisplayOption Display { get; set; }
    public string Name { get; set; }

    [DefaultValue(0)]
    public int LookupValueOrgID
    {
        get
        {
            EnsureChildControls();
            return Convert.ToInt32(String.IsNullOrEmpty(SelectOneHiddenValue.Value) ? "0" : SelectOneHiddenValue.Value);
        }

        set
        {
            EnsureChildControls();
            SelectOneHiddenValue.Value = value.ToString();
        }
    }

    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    public string Text
    {
        get
        {
            EnsureChildControls();
            return SelectOneTextbox.Text;
        }

        set
        {
            EnsureChildControls();
            SelectOneTextbox.Text = value;
        }
    }

    /// <summary>
    /// The minimum number of characters a user has to type before the autocompleter activates.
    /// </summary>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue(1)]
    [Localizable(true)]
    public int MinChars
    {
        get
        {
            int b = (ViewState["MinChars"] == null ? 1 : (int)ViewState["MinChars"]);
            return b;
        }
        set
        {
            ViewState["MinChars"] = value;
        }
    }

    /// <summary>
    /// The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Must be >= 1.
    /// </summary>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue(10)]
    [Localizable(true)]
    public int CacheLength
    {
        get
        {
            int b = (ViewState["CacheLength"] == null ? 10 : (int)ViewState["CacheLength"]);
            return b;
        }
        set
        {
            ViewState["CacheLength"] = value;
        }
    }

    public string OuterMarkupClientID
    {
        get { return "SelectOne_Container" + ClientID; }
    }

    /// <summary>
    /// If true, target input text is appended to
    /// If false, target input text is replaced
    /// </summary>
    public bool AppendSelectedTextToInput { get; set; }

    public virtual string ContainerClass
    {
        get { return "SelectOneContainer"; }
    }

    #endregion

    #region constructor
    public SelectOne()
    {
        SetCssClasses();
    }

    #endregion
    #region lifecycle overrides

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
        AddChildrenToControlCollection();
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        SetupClientEvents();
        ControlHelper.AddRequiredControl(this);

        var resourceName = string.Empty;

        var cs = Page.ClientScript;
        resourceName = "UI.Controls.resources.images.DropDownButton.gif";
        _selectOneDropDownImage.ImageUrl = cs.GetWebResourceUrl(GetType(), resourceName);

        SelectOneTextbox.Attributes.Add("lookupOrgID", LookupOrgID.ToString());
        SelectOneTextbox.Attributes.Add("cacheLength", CacheLength.ToString());
        SelectOneTextbox.Attributes.Add("service", Service);
        SelectOneTextbox.Attributes.Add("selectOneTextboxId", SelectOneTextbox.ClientID);
        SelectOneTextbox.Attributes.Add("selectOneHiddenValueId",SelectOneHiddenValue.ClientID);

    }

    #endregion

    #region private helpers
    private void SetCssClasses()
    {
        this.CssClass = ContainerClass + " AutocompleteContainer";
        _selectOneDropDownImage.CssClass = "SelectOneDropDownImage";
        SelectOneTextbox.CssClass = "SelectOneTextbox QuantifiTextBox";
        _selectOneTextboxContainer.CssClass = "SelectOneTextboxContainer";
        _selectOneDropdownImageContainer.CssClass = "SelectOneDropDownImageContainer";

    }

    private void SetupClientEvents()
    {
        ControlHelper.RegisterAutoCompleteScript(this);
        var resourceName = "UI.Controls.resources.scripts.SelectOne.js";

        string js;
        using (var sr = new StreamReader(GetType().Assembly.GetManifestResourceStream(resourceName)))
        {
            js = sr.ReadToEnd();
            sr.Close();
        }
        ClientScriptProxy.Current.RegisterStartupScript(this, typeof(SelectOne), "SelectOneJS", js, true);

        _selectOneDropDownImage.Attributes.Add("onclick", "SelectOne_ImageClick('" + SelectOneTextbox.ClientID + "');");
    }

    private void AddChildrenToControlCollection()
    {
        _selectOneTextboxContainer.Controls.Add(SelectOneTextbox);
        this.Controls.Add(_selectOneTextboxContainer);

        _selectOneDropdownImageContainer.Controls.Add(_selectOneDropDownImage);
        this.Controls.Add(_selectOneDropdownImageContainer);
        this.Controls.Add(SelectOneHiddenValue);
    }
    #endregion
}


选择许多:

[ToolboxData("<{0}:SelectMany runat=server></{0}:SelectMany>")]
public class SelectMany : SelectOne, ISelectMany
{
    #region structure

    private readonly Panel _selectedItemsPanel = new Panel();
    private readonly HiddenField _selectManyHiddenField = new HiddenField();

    public override string ContainerClass
    {
        get
        {
            return "SelectManyControlContainer";
        }
    }

    #endregion
    public SelectMany()
    {
        MultiSelect = true;
    }

    #region lifecycle overrides
    protected override void CreateChildControls()
    {
        base.CreateChildControls();


        _selectManyHiddenField.ID = "SelectedItemsHiddenValue";

        this.Controls.Add(_selectedItemsPanel);
        this.Controls.Add(_selectManyHiddenField);

        SelectOneTextbox.Attributes.Add("data-multiselect", MultiSelect.ToString());
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        var resourceName = "jquery.SelectedItemCollection.js";

        ClientScriptProxy.Current.RegisterClientScriptInclude(this, Page.ClientScript.GetWebResourceUrl(this.GetType(),resourceName));
        var serializer = new JavaScriptSerializer();
        var startupScript = String.Format("\n$('#{0}').each(function(){{" +
                                          "var selectedPlugin = $(this).SelectedItemCollection(" +
                                          "       {{" +
                                          "          itemData: {1}," +
                                          "          deleteImageUrl: '{2}'," +
                                          "          selectedTextId: '{3}', " +
                                          "          hiddenTextFieldId: '{4}' " +
                                          "       }});}});\n",
            this.ClientID,
            serializer.Serialize(SelectedItems),
            GetDeleteImageUrl(),
            SelectOneTextbox.ClientID,
            _selectManyHiddenField.ClientID
            );
        ClientScriptProxy.Current.RegisterStartupScript(this,this.GetType(),"SelectedItemsJs_" + this.ClientID,startupScript,true);
    }
    #endregion

    #region public api
    public void BindForm()
    {
        EnsureChildControls();
        this.DataBind();
        var jsonString = _selectManyHiddenField.Value;

        SelectedItems.Clear();
        if (!jsonString.IsNullOrEmpty())
        {
            Json.Decode<IEnumerable<LookupItem>>(jsonString).ForEach(li => SelectedItems.Add(li));
        }

    }
    #endregion

    private string GetDeleteImageUrl()
    {
        var cs = Page.ClientScript;
        const string resourceName = "UI.Controls.resources.images.close.gif";
        return cs.GetWebResourceUrl(this.GetType(), resourceName);
    }


}

最佳答案

好吧,那真是愚蠢。它花了我永远的时间。基本上,不要滥用确保儿童控件()方法。基类在调用某些属性之前就调用了它。恢复ViewState之后但在我无法检查值之前,这称为RecreateChildControls()。

为了解决这个问题,我在基类和派生类的OnInit重写中添加了sureChildControls()。这样,将正确创建我的所有控件,并在创建后还原ViewState。

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        EnsureChildControls();
    }

09-25 18:18