selectedindexchanged event not firing in custom control derived from datagrid

J

John Blair

Hi,

I am adding a row of dropdownlist controls to my datagrid in a custom
control
- i am adding a selectedindexchanged event to each of these ddls with
autopostback set to true. The postback happens but the selectedindexchanged
event does not fire? I am creating the ddls in the overriden
CreateChildControls method of the control. Note: the ddl viewstate is saved
and restored ok in this control but the selectedindexchanged event handler
just not trigger.

Any idea how to wire this event up such that it fires as expected?

thanks a lot!
 
A

Alessandro Zifiglio

hi John, you need to find your dropdownlist in your datagrids, onItemCreated
or onItemDataBound method and once you find the control in question(your
dropdownlist in this case) hookup its event there.
Regards,
Alessandro Zifiglio
 
A

Alessandro Zifiglio

John, now that i re-read your post, its really not clear to me what the
connection with the datagrid and your dropdownlist is, since you clearly
state that the dropdownlist is created in a custom control, so are you
saying that you wire up the events in your custom control ? however no
events are fired ? Maybe some sample code is better.
I responded thinking you had your dropdownlist as child controls of the
datagrid control :)
Apologies =P
Alessandro
 
J

John Blair

Hi Alessandro ,

Thanks for replaying ...it is a custom contol derived from datagrid ....
here's the relevant snippet!


protected override void CreateControlHierarchy(bool useDataSource)
..
..
..
CreateFilterControlHierarchy(useDataSource));

..
..
..

protected void CreateFilterControlHierarchy(bool useDataSource){

//Data Grid table is the first control in the collection.
Table dataGridTable = Controls[0] as Table;
Page.Trace.Write("DataGrid:Begin CreateFilterControlHierarchy");


//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the column
//header text or sort link.
int i =0;
foreach (Control c in dataGridItem.Controls){
DropDownList ddl = new DropDownList();
//Begin tracking viewstate.
c.Controls.AddAt(c.Controls.Count,ddl);

//Populate the ddls.
//Note: If not using the datasource rely on viewstate to restore
//ddl filter content.
string columnName =
DataSourceDataSet.Tables[0].Columns.ColumnName;
ddl.ID=columnName;

ddl.AutoPostBack=true;

//THIS IS IGNORED!!!!!
ddl.SelectedIndexChanged += new EventHandler(
this.DataGridDropDownList_SelectedIndexChanged);

if (useDataSource){
PopulateDDL(
ddl,
DataSourceDataSet.Tables[0],
columnName);

//Initialise view state.
ViewState[columnName] = ddl.Items[0].Text;
}
else{
//Use existing viewstate.
}

}
Page.Trace.Write("DataGrid:End CreateFilterControlHierarchy");


}
..
..
 
A

Alessandro Zifiglio

hi John, seems like working code. I have tried to test your code and it
seems to works well, with your selectedIndexChanged event triggering as
expected :

public class MyCustomDataGrid : DataGrid
{
protected override void CreateControlHierarchy(bool useDataSource)
{
base.CreateControlHierarchy(useDataSource);
Table dataGridTable = Controls[0] as Table;
//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the column
//header text or sort link.
foreach (Control c in dataGridItem.Controls)
{
System.Web.UI.WebControls.DropDownList DropDownList1 = new
DropDownList();
c.Controls.AddAt(c.Controls.Count, DropDownList1);
DropDownList1.AutoPostBack = true;
DropDownList1.SelectedIndexChanged += new
System.EventHandler(this.DropDownList1_SelectedIndexChanged);
if (useDataSource)
{
DropDownList1.Items.Add(new ListItem("1", "a"));
DropDownList1.Items.Add(new ListItem("2", "b"));
DropDownList1.Items.Add(new ListItem("3", "c"));
}
}


}
private void DropDownList1_SelectedIndexChanged(object sender,
System.EventArgs e)
{
Context.Response.Write("Raised dropdownlist
selectedindexchanged");
}
}


Page to test the custom DataGrid Control :
----------------------------------------


protected void Page_Load(object sender, EventArgs e)
{
if (!this.Page.IsPostBack)
{
this.MyCustomDataGrid1.DataSource = CreateDataSource();
this.MyCustomDataGrid1.DataBind();
}
}
ICollection CreateDataSource()
{
DataTable dt = new DataTable();
DataRow dr;

dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));

for (int i = 0; i < 9; i++)
{
dr = dt.NewRow();

dr[0] = i;
dr[1] = "Item " + i.ToString();
dr[2] = 1.23 * (i + 1);

dt.Rows.Add(dr);
}

DataView dv = new DataView(dt);
return dv;
}

John Blair said:
Hi Alessandro ,

Thanks for replaying ...it is a custom contol derived from datagrid ....
here's the relevant snippet!


protected override void CreateControlHierarchy(bool useDataSource)
.
.
.
CreateFilterControlHierarchy(useDataSource));

.
.
.

protected void CreateFilterControlHierarchy(bool useDataSource){

//Data Grid table is the first control in the collection.
Table dataGridTable = Controls[0] as Table;
Page.Trace.Write("DataGrid:Begin CreateFilterControlHierarchy");


//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the column
//header text or sort link.
int i =0;
foreach (Control c in dataGridItem.Controls){
DropDownList ddl = new DropDownList();
//Begin tracking viewstate.
c.Controls.AddAt(c.Controls.Count,ddl);

//Populate the ddls.
//Note: If not using the datasource rely on viewstate to restore
//ddl filter content.
string columnName =
DataSourceDataSet.Tables[0].Columns.ColumnName;
ddl.ID=columnName;

ddl.AutoPostBack=true;

//THIS IS IGNORED!!!!!
ddl.SelectedIndexChanged += new EventHandler(
this.DataGridDropDownList_SelectedIndexChanged);

if (useDataSource){
PopulateDDL(
ddl,
DataSourceDataSet.Tables[0],
columnName);

//Initialise view state.
ViewState[columnName] = ddl.Items[0].Text;
}
else{
//Use existing viewstate.
}

}
Page.Trace.Write("DataGrid:End CreateFilterControlHierarchy");


}
.
.
 
J

John Blair

Hi Alessandro,

You're a genius! Thanks a lot!

Your sample did the trick - i spent ages trying to work out why your sample
worked and my "working code" did not as they
essentially do the same thing.

Finally found it (and it really pissed me off!).
The only difference between your code and mine was how we loaded the
dropdownlist controls.
You populate both the text and the value with non-null data, I populated all
the values with a null string.
When i changed the value string.Empty to be the same as the text - my code
started receiving the events.
I can't believe it - i am only interested in the text value and not the
value so didn't see any point in populating it.
I did some research and it turns out that the event does not fire on change
of index - it only
fires if the index is changed and the option VALUE for the new index has
also changed.

Thank you very much for your help! .... John.



Your code: DropDownList1.Items.Add(new ListItem("1", "a"));
If you replace "a","b","c" with string.Emtpy you will notice the events stop
arriving!
Because the option value never changes from its initial setting
string.Empty!.

My Code: ddl.Items.Add( new ListItem(dataRowView[columnName].ToString(),
string.Empty));




Alessandro Zifiglio said:
hi John, seems like working code. I have tried to test your code and it
seems to works well, with your selectedIndexChanged event triggering as
expected :

public class MyCustomDataGrid : DataGrid
{
protected override void CreateControlHierarchy(bool useDataSource)
{
base.CreateControlHierarchy(useDataSource);
Table dataGridTable = Controls[0] as Table;
//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the
column
//header text or sort link.
foreach (Control c in dataGridItem.Controls)
{
System.Web.UI.WebControls.DropDownList DropDownList1 = new
DropDownList();
c.Controls.AddAt(c.Controls.Count, DropDownList1);
DropDownList1.AutoPostBack = true;
DropDownList1.SelectedIndexChanged += new
System.EventHandler(this.DropDownList1_SelectedIndexChanged);
if (useDataSource)
{
DropDownList1.Items.Add(new ListItem("1", "a"));
DropDownList1.Items.Add(new ListItem("2", "b"));
DropDownList1.Items.Add(new ListItem("3", "c"));
}
}


}
private void DropDownList1_SelectedIndexChanged(object sender,
System.EventArgs e)
{
Context.Response.Write("Raised dropdownlist
selectedindexchanged");
}
}


Page to test the custom DataGrid Control :
----------------------------------------


protected void Page_Load(object sender, EventArgs e)
{
if (!this.Page.IsPostBack)
{
this.MyCustomDataGrid1.DataSource = CreateDataSource();
this.MyCustomDataGrid1.DataBind();
}
}
ICollection CreateDataSource()
{
DataTable dt = new DataTable();
DataRow dr;

dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));

for (int i = 0; i < 9; i++)
{
dr = dt.NewRow();

dr[0] = i;
dr[1] = "Item " + i.ToString();
dr[2] = 1.23 * (i + 1);

dt.Rows.Add(dr);
}

DataView dv = new DataView(dt);
return dv;
}

John Blair said:
Hi Alessandro ,

Thanks for replaying ...it is a custom contol derived from datagrid ....
here's the relevant snippet!


protected override void CreateControlHierarchy(bool useDataSource)
.
.
.
CreateFilterControlHierarchy(useDataSource));

.
.
.

protected void CreateFilterControlHierarchy(bool useDataSource){

//Data Grid table is the first control in the collection.
Table dataGridTable = Controls[0] as Table;
Page.Trace.Write("DataGrid:Begin CreateFilterControlHierarchy");


//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the column
//header text or sort link.
int i =0;
foreach (Control c in dataGridItem.Controls){
DropDownList ddl = new DropDownList();
//Begin tracking viewstate.
c.Controls.AddAt(c.Controls.Count,ddl);

//Populate the ddls.
//Note: If not using the datasource rely on viewstate to restore
//ddl filter content.
string columnName =
DataSourceDataSet.Tables[0].Columns.ColumnName;
ddl.ID=columnName;

ddl.AutoPostBack=true;

//THIS IS IGNORED!!!!!
ddl.SelectedIndexChanged += new EventHandler(
this.DataGridDropDownList_SelectedIndexChanged);

if (useDataSource){
PopulateDDL(
ddl,
DataSourceDataSet.Tables[0],
columnName);

//Initialise view state.
ViewState[columnName] = ddl.Items[0].Text;
}
else{
//Use existing viewstate.
}

}
Page.Trace.Write("DataGrid:End CreateFilterControlHierarchy");


}
.
.

 
A

Alessandro Zifiglio

You are welcome John :)
Regards,
Alessandro Zifiglio
John Blair said:
Hi Alessandro,

You're a genius! Thanks a lot!

Your sample did the trick - i spent ages trying to work out why your
sample worked and my "working code" did not as they
essentially do the same thing.

Finally found it (and it really pissed me off!).
The only difference between your code and mine was how we loaded the
dropdownlist controls.
You populate both the text and the value with non-null data, I populated
all the values with a null string.
When i changed the value string.Empty to be the same as the text - my code
started receiving the events.
I can't believe it - i am only interested in the text value and not the
value so didn't see any point in populating it.
I did some research and it turns out that the event does not fire on
change of index - it only
fires if the index is changed and the option VALUE for the new index has
also changed.

Thank you very much for your help! .... John.



Your code: DropDownList1.Items.Add(new ListItem("1", "a"));
If you replace "a","b","c" with string.Emtpy you will notice the events
stop arriving!
Because the option value never changes from its initial setting
string.Empty!.

My Code: ddl.Items.Add( new ListItem(dataRowView[columnName].ToString(),
string.Empty));




Alessandro Zifiglio said:
hi John, seems like working code. I have tried to test your code and it
seems to works well, with your selectedIndexChanged event triggering as
expected :

public class MyCustomDataGrid : DataGrid
{
protected override void CreateControlHierarchy(bool useDataSource)
{
base.CreateControlHierarchy(useDataSource);
Table dataGridTable = Controls[0] as Table;
//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the
column
//header text or sort link.
foreach (Control c in dataGridItem.Controls)
{
System.Web.UI.WebControls.DropDownList DropDownList1 = new
DropDownList();
c.Controls.AddAt(c.Controls.Count, DropDownList1);
DropDownList1.AutoPostBack = true;
DropDownList1.SelectedIndexChanged += new
System.EventHandler(this.DropDownList1_SelectedIndexChanged);
if (useDataSource)
{
DropDownList1.Items.Add(new ListItem("1", "a"));
DropDownList1.Items.Add(new ListItem("2", "b"));
DropDownList1.Items.Add(new ListItem("3", "c"));
}
}


}
private void DropDownList1_SelectedIndexChanged(object sender,
System.EventArgs e)
{
Context.Response.Write("Raised dropdownlist
selectedindexchanged");
}
}


Page to test the custom DataGrid Control :
----------------------------------------


protected void Page_Load(object sender, EventArgs e)
{
if (!this.Page.IsPostBack)
{
this.MyCustomDataGrid1.DataSource = CreateDataSource();
this.MyCustomDataGrid1.DataBind();
}
}
ICollection CreateDataSource()
{
DataTable dt = new DataTable();
DataRow dr;

dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));

for (int i = 0; i < 9; i++)
{
dr = dt.NewRow();

dr[0] = i;
dr[1] = "Item " + i.ToString();
dr[2] = 1.23 * (i + 1);

dt.Rows.Add(dr);
}

DataView dv = new DataView(dt);
return dv;
}

John Blair said:
Hi Alessandro ,

Thanks for replaying ...it is a custom contol derived from datagrid ....
here's the relevant snippet!


protected override void CreateControlHierarchy(bool useDataSource)
.
.
.
CreateFilterControlHierarchy(useDataSource));

.
.
.

protected void CreateFilterControlHierarchy(bool useDataSource){

//Data Grid table is the first control in the collection.
Table dataGridTable = Controls[0] as Table;
Page.Trace.Write("DataGrid:Begin CreateFilterControlHierarchy");


//Get the table header row.
DataGridItem dataGridItem = dataGridTable.Controls[0] as
DataGridItem;

//Add a ddl to each column in the header.
//Use style sheet "td.DataGridHeaderCell select" to make
//sure each ddl is on a new line with spacing between the column
//header text or sort link.
int i =0;
foreach (Control c in dataGridItem.Controls){
DropDownList ddl = new DropDownList();
//Begin tracking viewstate.
c.Controls.AddAt(c.Controls.Count,ddl);

//Populate the ddls.
//Note: If not using the datasource rely on viewstate to restore
//ddl filter content.
string columnName =
DataSourceDataSet.Tables[0].Columns.ColumnName;
ddl.ID=columnName;

ddl.AutoPostBack=true;

//THIS IS IGNORED!!!!!
ddl.SelectedIndexChanged += new EventHandler(
this.DataGridDropDownList_SelectedIndexChanged);

if (useDataSource){
PopulateDDL(
ddl,
DataSourceDataSet.Tables[0],
columnName);

//Initialise view state.
ViewState[columnName] = ddl.Items[0].Text;
}
else{
//Use existing viewstate.
}

}
Page.Trace.Write("DataGrid:End CreateFilterControlHierarchy");


}
.
.


 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top