Dynamic columns and NamingContainer

T

Tumurbaatar S.

I dynamically add columns to DataGrid as described in MSDN
articles "Top Questions about the DataGrid Web Server Control"
and "Creating Web Server Control Templates Programmatically".
The columns are template based and all they use a same template
producer. In the edit mode (ListItemType.EditItem) the template
adds textbox and validator controls to a column as:

public void InstantiateIn(System.Web.UI.Control container)
{
TextBox tb = new TextBox();
tb.Text = "";
tb.ID = "MyTextBox";
container.Controls.Add(tb);
CompareValidator val = new CompareValidator();
val.ControlToValidate(tb.ID);
container.Controls.Add(val);
}

During run-time this method throws exception like "... multiple controls
have
same ID: MyTextBox...". Of course, if there was no need to use the
validator,
I probably will not touch ID of the textbox and leave it with a default
value (empty?).
But the validator requires this ID for its ControlToValidate property.
Any workarounds?

P.S. In above method, the "container" parameter is type of TableCell.
But its Parent and NamingContainer properties are undefined (I checked
it during debugging with QuickWatch). Why?
I expected that TableCell's Parent will be DataGridItem and NamingContainer
will be DataGridItem or DataGrid itself. I ask it because I want to
reference
a parent column from above InstantiateIn() method to create IDs based on
a column information (column index or something else).
 
G

Guest

The error you got means that you instantiated more than one column using the
same Template that contained more than one Textbox in the datagriditem with
the same ID. You can solve that by assigning the ID upon databinding:
1- Modify the InstaniateIn method to look like this:

TextBox tb = new TextBox();
container.Controls.Add(tb);
RequiredFieldValidator val = new RequiredFieldValidator ();
container.Controls.Add(val);
container.DataBinding += new EventHandler(ItemContainer_DataBinding);

2- Add another method like this:
void ItemContainer_DataBinding(object sender, EventArgs e)
{
TableCell td= (TableCell)sender; //gets the container
//gets the naming container that you wanted
DataGridItem dgItem = ((DataGridItem )td.NamingContainer );
//get the cell # within the tablerow
int cellNo=-0;
foreach (TableCell tc in dgItem.Cells)
{
if (tc == td) break;
cellNo++;
}
//the first control within the cell is the textbox
TextBox tb = td.Controls [0] as TextBox ;
//assign a unique ID for each cell within the same TableRow
tb.ID = "MyTextBox" + cellNo;
//the validator is the second control within the container
RequiredFieldValidator val = td.Controls[1] as RequiredFieldValidator;
//set the validator properties
val.ControlToValidate = tb.ID;
val.ErrorMessage = "Cannot leave blank";
//add a value to databind to the TextBox
tb.Text = ((DataRowView)dgItem.DataItem)[0].ToString ();
}
 
T

Tumurbaatar S.

Thank you!
I also found something like your recommendation.
My DataGrid already uses ItemCreated event so
I put there a code that sets these IDs.
Thank you again!

Phillip Williams said:
The error you got means that you instantiated more than one column using
the
same Template that contained more than one Textbox in the datagriditem
with
the same ID. You can solve that by assigning the ID upon databinding:
1- Modify the InstaniateIn method to look like this:

TextBox tb = new TextBox();
container.Controls.Add(tb);
RequiredFieldValidator val = new RequiredFieldValidator ();
container.Controls.Add(val);
container.DataBinding += new EventHandler(ItemContainer_DataBinding);

2- Add another method like this:
void ItemContainer_DataBinding(object sender, EventArgs e)
{
TableCell td= (TableCell)sender; //gets the container
//gets the naming container that you wanted
DataGridItem dgItem = ((DataGridItem )td.NamingContainer );
//get the cell # within the tablerow
int cellNo=-0;
foreach (TableCell tc in dgItem.Cells)
{
if (tc == td) break;
cellNo++;
}
//the first control within the cell is the textbox
TextBox tb = td.Controls [0] as TextBox ;
//assign a unique ID for each cell within the same TableRow
tb.ID = "MyTextBox" + cellNo;
//the validator is the second control within the container
RequiredFieldValidator val = td.Controls[1] as RequiredFieldValidator;
//set the validator properties
val.ControlToValidate = tb.ID;
val.ErrorMessage = "Cannot leave blank";
//add a value to databind to the TextBox
tb.Text = ((DataRowView)dgItem.DataItem)[0].ToString ();
}
--
HTH,
Phillip Williams
http://www.societopia.net
http://www.webswapp.com


Tumurbaatar S. said:
I dynamically add columns to DataGrid as described in MSDN
articles "Top Questions about the DataGrid Web Server Control"
and "Creating Web Server Control Templates Programmatically".
The columns are template based and all they use a same template
producer. In the edit mode (ListItemType.EditItem) the template
adds textbox and validator controls to a column as:

public void InstantiateIn(System.Web.UI.Control container)
{
TextBox tb = new TextBox();
tb.Text = "";
tb.ID = "MyTextBox";
container.Controls.Add(tb);
CompareValidator val = new CompareValidator();
val.ControlToValidate(tb.ID);
container.Controls.Add(val);
}

During run-time this method throws exception like "... multiple controls
have
same ID: MyTextBox...". Of course, if there was no need to use the
validator,
I probably will not touch ID of the textbox and leave it with a default
value (empty?).
But the validator requires this ID for its ControlToValidate property.
Any workarounds?

P.S. In above method, the "container" parameter is type of TableCell.
But its Parent and NamingContainer properties are undefined (I checked
it during debugging with QuickWatch). Why?
I expected that TableCell's Parent will be DataGridItem and
NamingContainer
will be DataGridItem or DataGrid itself. I ask it because I want to
reference
a parent column from above InstantiateIn() method to create IDs based on
a column information (column index or something else).
 

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

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top