I have a bit of a situation. Im new to asp but old hat with .net winforms. I am currently generating asp pages dynamically. Recently I was asked to put a filter dropdown into a column header. So I created a method that generates the template and the column and adds the Label for the name and the drop down. No big deal. Originally I couldn't get the event to raise so I set it to AutoPostBack = true and the event fired but the value isn't being retained.
My Debugging revealed some interesting information. When I first select a value in the dropdown list. I noticed the databind fires then the SaveViewState goes of (Which I over rode to solve multiple problems at once), then the OnSelectedValuechange Fires which has the right value in it but the Save Viewstate has already passed. then the Databind event occurs a second time and the original value is lost because of the recreation of the control.
So I guess my question here is: Is there a way to raise the event without the AutoPostBack Being set to true?
OR
Is there a way to dictate when Save and load viewstate fire?
OR
is there a way to force the OnSelectedValueChanged event to fire sooner?
Or am I missing something?
Here is the code for creating the Template:
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();
}
}
}
As you can probably tell I've tried several solutions and spent a couple days trying to figure this out. One thing I did notice is if I remove the event the value passes to and from my save and view load state overrides with no issue.
Here is where they are added to the grid:
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);
And last but not least the subclassed(I had to to keep common Properties between my controls so I could override the viewstate) 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", ""));
}
}
}