摘要:我有一个动态添加到页面的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();
}