我有点情况。我是asp的新手,但是.net winforms的旧帽子。我目前正在动态生成asp页面。最近我被要求将过滤器下拉列表放入列标题中。所以我创建了一个生成模板和列的方法,并为名称和下拉列表添加了Label。没什么大不了。最初我无法提升事件,所以我将其设置为AutoPostBack = true并且事件被触发但该值未被保留。
我的调试显示了一些有趣的信息。当我第一次在下拉列表中选择一个值时。我注意到数据绑定触发然后SaveViewState(我一次过来解决多个问题),然后OnSelectedValuechange Fires中有正确的值,但Save Viewstate已经通过了。然后Databind事件第二次发生,原始值因重新创建控件而丢失。
所以我想我的问题是:有没有办法在不将AutoPostBack设置为true的情况下引发事件?
OR
有没有办法在保存并加载viewstate fire时指示?
OR
有没有办法强制OnSelectedValueChanged事件更快启动?
或者我错过了什么?
以下是创建模板的代码:
public class GTemplate : Control, ITemplate
{
protected Control InternalControl;
private TemplateType tempType;
internal string InnerControlDataSource;
internal string DataTextField;
internal string DataValueField;
internal string InnerControlName;
internal string HeaderText;
internal string ItemsDataField;
public EventHandler EventItem;
ControlType innerControl;
public GTemplate(TemplateType tt,WSControlItem Item,EventHandler EventItem)
{
innerControl = (ControlType)Convert.ToInt16(Item.GetAttributeValueByID("InnerControlType"));
InnerControlName = Item.GetAttributeValueByID("InnerControlName");
innerBlocking = PageControl;
this.EventItem = EventItem;
InnerControlDataSource = Item.DataSourceName;
DataTextField = Item.GetAttributeValueByID("DataTextField");
DataValueField = Item.GetAttributeValueByID("DataValueField");
ItemsDataField = Item.GetAttributeValueByID("datafield");
HeaderText = Item.Text;
EventItem += EventItem;
tempType = tt;
}
public void InstantiateIn(Control container)
{
switch (tempType)
{
case TemplateType.Header:
switch (innerControl)
{
case ControlType.DropDownList:
GLabel glbl = new GLabel();
glbl.Text = HeaderText;
container.Controls.Add(glbl);
GDropDownList ddl = new GDropDownList();
ddl.ID = InnerControlName;
ddl.isFilter = true;
ddl.DataSourceID = InnerControlDataSource;
ddl.DataTextField = DataTextField;
ddl.DataValueField = DataValueField;
ddl.AutoPostBack = true;
ddl.SelectedIndexChanged += new EventHandler(EventItem);
container.Controls.Add(ddl);
break;
}
break;
case TemplateType.EditItem:
GLabel lbl = new GLabel();
lbl.ID = "Label_" + InnerControlName;
lbl.DataBinding += new EventHandler(tb1_DataBinding);
lbl.Text = "'<%# Eval(" + ItemsDataField + ") %>'";
container.Controls.Add(lbl);
break;
}
}
protected void tb1_DataBinding(object sender, EventArgs e)
{
GLabel txtdata = (GLabel)sender;
GridViewRow container = (GridViewRow)txtdata.NamingContainer;
object dataValue = DataBinder.Eval(container.DataItem, ItemsDataField);
if (dataValue != DBNull.Value)
{
txtdata.Text = dataValue.ToString();
}
}
}
你可能会说我尝试了几种解决方案并花了几天时间试图解决这个问题。我注意到的一件事是,如果我删除了值传递给我的保存和查看加载状态覆盖的事件没有问题。
以下是将它们添加到网格中的位置:
GTemplateField gtf = new GTemplateField(Item, Control_LoadBehavior);
GGridView ggv3 = (GGridView)Container;
gtf.HeaderText = Item.Text;
gtf.HeaderTemplate = new GTemplate(TemplateType.Header, Item, Control_LoadBehavior);
gtf.ItemTemplate = new GTemplate(TemplateType.EditItem, Item, Control_LoadBehavior);
ggv3.Columns.Add(gtf);
最后但并非最不重要的是子类(我必须在我的控件之间保留公共属性,以便我可以覆盖视图状态)DropdownList:
/// <summary>
/// A custom DropDownList class that extends the functionality of its base class and includes additional properties.
/// </summary>
public class GDropDownList: DropDownList
{
public bool isFilter { get; set; }
/// <summary>
/// The default constructor for a GDropDownList object.
/// </summary>
public GDropDownList()
: base()
{
}
internal EventHandler InnerEvent;
/// <summary>
/// Returns the text property of the control.
/// </summary>
public string ReturnValue
{
get { return SelectedValue; }
}
/// <summary>
/// Currently, this variable is not being used.
/// </summary>
public string ReturnSetting;
/// <summary>
/// Returns the text property of the control. To set the value, see SetViewStateData.
/// </summary>
public string GetViewStateData
{
get { return SelectedValue; }
}
/// <summary>
/// Sets the text property of the control. To get the value, see GetViewStateData.
/// </summary>
public string SetViewStateData
{
set { SelectedValue = value; }
}
/// <summary>
/// Currently, this property is not being used.
/// </summary>
public string GetComparitiveValue
{
get { return ""; }
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
string i = SelectedValue;//i need to store the value if its not blank here, Where the fuck do I store it?
base.OnSelectedIndexChanged(e);
}
public override void DataBind()
{
base.DataBind();
if (isFilter)
Items.Insert(0, new ListItem("Select Filter", ""));
}
}
}
答案 0 :(得分:0)
因此经过一些研究和更多的试验和错误后,我发现当OnSelectedValueChange被触发并且SQL数据集重新填充数据源时,Control被销毁了。所以我按照这篇文章[link] 'Session' does not exist in the current context中的建议设置了一个围绕Session状态的包装器,一切正常。
以下是我改编的代码:
public class MySession
{
// private constructor
private MySession()
{
Filters = new List<PageValueItem>();
}
// Gets the current session.
public static MySession Current
{
get
{
MySession session =
(MySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new MySession();
HttpContext.Current.Session["__MySession__"] = session;
}
return session;
}
}
public static void SaveFilterValue(string ID, string value)
{
MySession session =
(MySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new MySession();
session.Filters.Add(new PageValueItem(ID, value));
HttpContext.Current.Session["__MySession__"] = session;
}
else
{
session.Filters.Add(new PageValueItem(ID, value));
HttpContext.Current.Session["__MySession__"] = session;
}
}
public static string GetFilterValue(string ID)
{
string retVal = null;
MySession session =
(MySession)HttpContext.Current.Session["__MySession__"];
if (session != null)
{
foreach(PageValueItem pvi in session.Filters)
{
if(pvi.ID == ID)
{
retVal = pvi.Value;
}
}
}
return retVal;
}
private List<PageValueItem> Filters;
}
PageValueItem只是一个存储DropDownList的ID和值的对象。