Dynamic columns and NamingContainer

Discussion in 'ASP .Net Datagrid Control' started by Tumurbaatar S., Nov 27, 2005.

  1. 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).
    Tumurbaatar S., Nov 27, 2005
    #1
    1. Advertising

  2. 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." wrote:

    > 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).
    >
    >
    >
    >
    >
    >
    >
    >
    Phillip Williams, Nov 27, 2005
    #2
    1. Advertising

  3. 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" <> wrote in message
    news:...
    > 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." wrote:
    >
    >> 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).
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    Tumurbaatar S., Nov 27, 2005
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. msmail.microsoft.com

    NamingContainer and UserControl

    msmail.microsoft.com, Oct 10, 2004, in forum: ASP .Net
    Replies:
    8
    Views:
    4,187
    Shahar Prish
    Oct 13, 2004
  2. Tumurbaatar S.

    Dynamic columns and NamingContainer

    Tumurbaatar S., Nov 27, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    3,438
    Tumurbaatar S.
    Nov 27, 2005
  3. Rob Blij
    Replies:
    0
    Views:
    457
    Rob Blij
    May 25, 2006
  4. Rob Blij
    Replies:
    0
    Views:
    1,000
    Rob Blij
    May 25, 2006
  5. Dan
    Replies:
    1
    Views:
    495
    =?Utf-8?B?TWlsb3N6IFNrYWxlY2tpIFtNQ0FEXQ==?=
    Apr 4, 2007
Loading...

Share This Page