2013-10-09 28 views
2

摘要:我有一個動態添加到頁面的Web控件。該控件具有HiddenField子控件。我將控件的ClientID傳遞給一個將值設置爲字符串的jquery小部件(將json轉換爲字符串)。將表單發回服務器時,HiddenField的值爲空字符串。我的值在Request.Form [UniqueID]對象中。該值正在返回到服務器。問題是,當我需要該值而無需修改大量遺留代碼時,我無法訪問Request對象。發佈回服務器時,JQuery修改的隱藏字段值爲空

奇怪的是,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); 
    } 


} 
+0

你說SelectMany從SelectOne繼承,它可以正常工作,但你向我們展示SelectOneP1S。你是否繼承了你認爲你的課程? – KennyZ

+0

我很抱歉,我在複製代碼時將SelectOneP1S重命名爲SelectOne。其餘的代碼是一樣的。我糾正了錯字。 –

回答

1

嗯,這是愚蠢的東西。我永遠需要找到它。基本上,不要誤用EnsureChildControls()方法。基類在訪問它的某些屬性之前調用它。這在ViewState恢復之後調用了RecreateChildControls(),但是在我檢查值之前。

要解決此問題,我在OnInit覆蓋中爲基類和派生類添加了EnsureChildControls()。這樣,我的所有控件都將被正確創建,並且ViewState在創建後被恢復。

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