How to create section 508 compliant Data Grid - ASP.NET v1.1

Discussion in 'ASP .Net' started by Corey B, Jun 21, 2006.

  1. Corey B

    Corey B Guest

    I have a data grid that has three columns: First Name, Middle Name,
    and Last Name. The grid has a list of people with a blank row at the
    bottom of the grid (in the footer) that allows the user to add a new
    person to the list. There is also an Edit button at the end of each
    row that allows the user to edit a particular row. So far - no problem
    - easy to do.

    I have been asked to make the grid section 508 compliant. The
    requirement is that the column headers must have labels that reference
    the text boxes in the footer row. On a normal web form it would look
    like this:

    <label for="txtFirstName">First Name</label>
    <asp:textbox id="txtFirstName" runat="server" />

    This allows a text reader to figure out that the words "First Name" are
    associated with the text box "txtFirstName" and helps a blind person
    understand how to fill out the form.

    Now, back to my problem. I need to figure out a way to get the header
    of a Data Grid column to work the same way. The biggest problem is
    that I have no idea what the ClientID of the textbox will be. So I
    definitely can't hard code the <label> item.

    Does anyone have any idea how I can do this?

    Thanks,
    Corey
    Corey B, Jun 21, 2006
    #1
    1. Advertising

  2. Corey B

    vMike Guest

    "Corey B" <> wrote in message
    news:...
    > I have a data grid that has three columns: First Name, Middle Name,
    > and Last Name. The grid has a list of people with a blank row at the
    > bottom of the grid (in the footer) that allows the user to add a new
    > person to the list. There is also an Edit button at the end of each
    > row that allows the user to edit a particular row. So far - no problem
    > - easy to do.
    >
    > I have been asked to make the grid section 508 compliant. The
    > requirement is that the column headers must have labels that reference
    > the text boxes in the footer row. On a normal web form it would look
    > like this:
    >
    > <label for="txtFirstName">First Name</label>
    > <asp:textbox id="txtFirstName" runat="server" />
    >
    > This allows a text reader to figure out that the words "First Name" are
    > associated with the text box "txtFirstName" and helps a blind person
    > understand how to fill out the form.
    >
    > Now, back to my problem. I need to figure out a way to get the header
    > of a Data Grid column to work the same way. The biggest problem is
    > that I have no idea what the ClientID of the textbox will be. So I
    > definitely can't hard code the <label> item.
    >
    > Does anyone have any idea how I can do this?
    >
    > Thanks,
    > Corey

    I have never looked at it that much but there is an accessibilty section in
    the sdk doc. It makes reference to a gridview property call
    UseAccessibleHeader. Maybe that will help or you might search the docs for
    Accessibility Support in ASP.NET or ASP.NET Controls and Accessibility

    Mike
    vMike, Jun 21, 2006
    #2
    1. Advertising

  3. Corey B

    addup Guest

    vMike wrote:
    > "Corey B" <> wrote in message
    > news:...
    > > I have a data grid that has three columns: First Name, Middle Name,
    > > and Last Name. The grid has a list of people with a blank row at the
    > > bottom of the grid (in the footer) that allows the user to add a new
    > > person to the list. There is also an Edit button at the end of each
    > > row that allows the user to edit a particular row. So far - no problem
    > > - easy to do.
    > >
    > > I have been asked to make the grid section 508 compliant. The
    > > requirement is that the column headers must have labels that reference
    > > the text boxes in the footer row. On a normal web form it would look
    > > like this:
    > >
    > > <label for="txtFirstName">First Name</label>
    > > <asp:textbox id="txtFirstName" runat="server" />
    > >
    > > This allows a text reader to figure out that the words "First Name" are
    > > associated with the text box "txtFirstName" and helps a blind person
    > > understand how to fill out the form.
    > >
    > > Now, back to my problem. I need to figure out a way to get the header
    > > of a Data Grid column to work the same way. The biggest problem is
    > > that I have no idea what the ClientID of the textbox will be. So I
    > > definitely can't hard code the <label> item.
    > >
    > > Does anyone have any idea how I can do this?
    > >
    > > Thanks,
    > > Corey

    > I have never looked at it that much but there is an accessibilty section in
    > the sdk doc. It makes reference to a gridview property call
    > UseAccessibleHeader. Maybe that will help or you might search the docs for
    > Accessibility Support in ASP.NET or ASP.NET Controls and Accessibility
    >
    > Mike


    Or do it the hard way (for framework 1.x).

    example:
    If your column is defined as
    <ASP:TEMPLATECOLUMN>
    <HEADERTEMPLATE><ASP:LABEL Runat="server" ID="lblHeaderLabel" >Name
    Column</ASP:LABEL></HEADERTEMPLATE>
    <ITEMTEMPLATE>&hellip;</ITEMTEMPLATE>
    <EDITITEMTEMPLATE>&hellip;</EDITITEMTEMPLATE>
    <FOOTERTEMPLATE><INPUT runat="server" id="txtFoot"
    class="raTextBox"></FOOTERTEMPLATE>
    </ASP:TEMPLATECOLUMN>

    your datagrid ItemDataBound handler can then do something analogus to
    (VB example)


    Static lblHeaderLabel As System.Web.UI.WebControls.Label
    Dim txtFoot As HtmlControls.HtmlInputText
    Try
    Select Case e.Item.ItemType
    Case ListItemType.Header
    lblHeaderLabel = e.Item.FindControl("lblHeaderLabel")
    Case ListItemType.Footer
    txtFoot = e.Item.FindControl("txtFoot")
    If Not lblHeaderLabel Is Nothing AndAlso _
    Not txtFoot Is Nothing Then
    lblHeaderLabel.Text = "<LABEL for='" & txtFoot.ClientID
    & "'>Name Column</LABEL>"
    End If
    End Select
    Catch ex As Exception : DisplayError(ex)
    End Try


    Hope this helps
    --- a ---
    addup, Jun 21, 2006
    #3
  4. Corey B

    Corey B Guest

    addup wrote:
    >
    > Or do it the hard way (for framework 1.x).
    >
    > example:
    > If your column is defined as
    > <ASP:TEMPLATECOLUMN>
    > <HEADERTEMPLATE><ASP:LABEL Runat="server" ID="lblHeaderLabel" >Name
    > Column</ASP:LABEL></HEADERTEMPLATE>
    > <ITEMTEMPLATE>&hellip;</ITEMTEMPLATE>
    > <EDITITEMTEMPLATE>&hellip;</EDITITEMTEMPLATE>
    > <FOOTERTEMPLATE><INPUT runat="server" id="txtFoot"
    > class="raTextBox"></FOOTERTEMPLATE>
    > </ASP:TEMPLATECOLUMN>
    >
    > your datagrid ItemDataBound handler can then do something analogus to
    > (VB example)
    >
    >
    > Static lblHeaderLabel As System.Web.UI.WebControls.Label
    > Dim txtFoot As HtmlControls.HtmlInputText
    > Try
    > Select Case e.Item.ItemType
    > Case ListItemType.Header
    > lblHeaderLabel = e.Item.FindControl("lblHeaderLabel")
    > Case ListItemType.Footer
    > txtFoot = e.Item.FindControl("txtFoot")
    > If Not lblHeaderLabel Is Nothing AndAlso _
    > Not txtFoot Is Nothing Then
    > lblHeaderLabel.Text = "<LABEL for='" & txtFoot.ClientID
    > & "'>Name Column</LABEL>"
    > End If
    > End Select
    > Catch ex As Exception : DisplayError(ex)
    > End Try
    >
    >
    > Hope this helps
    > --- a ---


    Thanks - I think that I am close to a solution now. I found that
    ASP.NET v1.1 SP1 has added a property to a label called
    AssociatedControlID. If you have the following:

    <asp:label id="myLabel" runat="server"
    AssociatedControlID="myTextBox">First Name"</asp:label>
    <asp:TextBox id="myTextBox" runat="server" />

    Then ASP.NET will spit out the following:
    <label for="myTextBox">First Name</label>

    And it's smart enough that it will emit the proper client id even if
    the text box is a nested control.

    So here's my problem. Let's say I have this set up:

    <ASP:TEMPLATECOLUMN>
    <HEADERTEMPLATE>
    <ASP:LABEL Runat="server" ID="lblHeaderLabel" >Name
    Column</ASP:LABEL>
    </HEADERTEMPLATE>
    <ITEMTEMPLATE>&hellip;</ITEMTEMPLATE>
    <EDITITEMTEMPLATE>&hellip;</EDITITEMTEMPLATE>
    <FOOTERTEMPLATE>
    <ASP:TEXTBOX ID="txtInput" RUNAT="Server" />
    </FOOTERTEMPLATE>
    </ASP:TEMPLATECOLUMN>

    Somehow I need to add the AssociatedControlID property to the
    lblHeaderLabel label control to get it to reference the txtInput
    textbox. So I am not sure where to add the code. Should it go in the
    header handler in ItemDataBound or should it go in the footer handler?
    It seems like if I put it in the header handler I wouldn't be able to
    reference a control that lives in the footer yet. But if I put it in
    the footer handler I wouldn't be able to modify a control that lives in
    the header. Any help would be appreciated.

    Thanks,
    Corey
    Corey B, Jun 21, 2006
    #4
  5. Corey B

    addup Guest

    Corey B wrote:
    > addup wrote:
    > >
    > > Or do it the hard way (for framework 1.x).
    > >
    > > example:
    > > If your column is defined as
    > > <ASP:TEMPLATECOLUMN>
    > > <HEADERTEMPLATE><ASP:LABEL Runat="server" ID="lblHeaderLabel" >Name
    > > Column</ASP:LABEL></HEADERTEMPLATE>
    > > <ITEMTEMPLATE>&hellip;</ITEMTEMPLATE>
    > > <EDITITEMTEMPLATE>&hellip;</EDITITEMTEMPLATE>
    > > <FOOTERTEMPLATE><INPUT runat="server" id="txtFoot"
    > > class="raTextBox"></FOOTERTEMPLATE>
    > > </ASP:TEMPLATECOLUMN>
    > >
    > > your datagrid ItemDataBound handler can then do something analogus to
    > > (VB example)
    > >
    > >
    > > Static lblHeaderLabel As System.Web.UI.WebControls.Label
    > > Dim txtFoot As HtmlControls.HtmlInputText
    > > Try
    > > Select Case e.Item.ItemType
    > > Case ListItemType.Header
    > > lblHeaderLabel = e.Item.FindControl("lblHeaderLabel")
    > > Case ListItemType.Footer
    > > txtFoot = e.Item.FindControl("txtFoot")
    > > If Not lblHeaderLabel Is Nothing AndAlso _
    > > Not txtFoot Is Nothing Then
    > > lblHeaderLabel.Text = "<LABEL for='" & txtFoot.ClientID
    > > & "'>Name Column</LABEL>"
    > > End If
    > > End Select
    > > Catch ex As Exception : DisplayError(ex)
    > > End Try
    > >
    > >
    > > Hope this helps
    > > --- a ---

    >
    > Thanks - I think that I am close to a solution now. I found that
    > ASP.NET v1.1 SP1 has added a property to a label called
    > AssociatedControlID. If you have the following:
    >
    > <asp:label id="myLabel" runat="server"
    > AssociatedControlID="myTextBox">First Name"</asp:label>
    > <asp:TextBox id="myTextBox" runat="server" />
    >
    > Then ASP.NET will spit out the following:
    > <label for="myTextBox">First Name</label>
    >
    > And it's smart enough that it will emit the proper client id even if
    > the text box is a nested control.
    >
    > So here's my problem. Let's say I have this set up:
    >
    > <ASP:TEMPLATECOLUMN>
    > <HEADERTEMPLATE>
    > <ASP:LABEL Runat="server" ID="lblHeaderLabel" >Name
    > Column</ASP:LABEL>
    > </HEADERTEMPLATE>
    > <ITEMTEMPLATE>&hellip;</ITEMTEMPLATE>
    > <EDITITEMTEMPLATE>&hellip;</EDITITEMTEMPLATE>
    > <FOOTERTEMPLATE>
    > <ASP:TEXTBOX ID="txtInput" RUNAT="Server" />
    > </FOOTERTEMPLATE>
    > </ASP:TEMPLATECOLUMN>
    >
    > Somehow I need to add the AssociatedControlID property to the
    > lblHeaderLabel label control to get it to reference the txtInput
    > textbox. So I am not sure where to add the code. Should it go in the
    > header handler in ItemDataBound or should it go in the footer handler?
    > It seems like if I put it in the header handler I wouldn't be able to
    > reference a control that lives in the footer yet. But if I put it in
    > the footer handler I wouldn't be able to modify a control that lives in
    > the header. Any help would be appreciated.
    >
    > Thanks,
    > Corey


    The answer is to do both.
    Get a reference to the label in the "header handler", and use it in the
    "footer handler"

    refer my earlier post.
    see the

    *Static* lblHeaderLabel As System.Web.UI.WebControls.Label

    to quote M$,
    Static variables remain in existence and retain their latest values
    after termination of the procedure in which they are declared.

    if AssociatedControlID works for you, change my earlier post from

    lblHeaderLabel.Text = "<LABEL for='" & txtFoot.ClientID & "'>Name
    Column</LABEL>"

    to

    lblHeaderLabel.AssociatedControlID = txtFoot.ClientID

    It's *ClientID*, not just ID

    Hope this helps,
    --- a ---
    PS: Notice the *ClientID*
    addup, Jun 22, 2006
    #5
  6. Corey B

    Corey B Guest

    Yeah - I tried that and it didn't work. Actually I think it is
    supposed to be just ID instead of ClientID but I tried both and neither
    works. Each time I get an error that says the following:

    Unable to find the control with id 'grdMyGrid__ctl2_txtFoot' that is
    associated with the Label 'lblHeaderLabel'.

    It's like it can't find the text box control that I am trying to
    associate the label with.

    I declared a Private variable at the top of the page called objLabel.
    Then in the "header handler" in the ItemDataBound event for the grid I
    set objLabel equal to the label that is in the header template.

    Then in the "footer handler" in the ItemDataBound event for the grid I
    did the following:

    Dim objTextBox As TextBox = e.Item.FindControl("txtFoot")
    objLabel.AssociatedControlID = objTextBox.ID

    (I also tried objTextBox.ClientID)

    Am I doing something wrong?

    Corey
    Corey B, Jun 22, 2006
    #6
  7. Corey B

    addup Guest

    Corey B wrote:
    > Yeah - I tried that and it didn't work. Actually I think it is
    > supposed to be just ID instead of ClientID but I tried both and neither
    > works. Each time I get an error that says the following:
    >
    > Unable to find the control with id 'grdMyGrid__ctl2_txtFoot' that is
    > associated with the Label 'lblHeaderLabel'.
    >
    > It's like it can't find the text box control that I am trying to
    > associate the label with.
    >
    > I declared a Private variable at the top of the page called objLabel.
    > Then in the "header handler" in the ItemDataBound event for the grid I
    > set objLabel equal to the label that is in the header template.
    >
    > Then in the "footer handler" in the ItemDataBound event for the grid I
    > did the following:
    >
    > Dim objTextBox As TextBox = e.Item.FindControl("txtFoot")
    > objLabel.AssociatedControlID = objTextBox.ID
    >
    > (I also tried objTextBox.ClientID)
    >
    > Am I doing something wrong?
    >
    > Corey


    There's something wrong, since it doesn't work :)

    You are correct, it should be ID, not ClientID, but that's not the
    answe either

    Here's what i would do to trace the problem/s
    1. comment out the objLabel.AssociatedControlID = objTextBox.ID line
    2. Check the HTML rendering of the datagridgrid. Confirm that
    'grdMyGrid__ctl2_txtFoot' is the clien-side id/name of the footer text
    box
    3. And the kicker - * don't * use AssociatedControlID, try the
    old-fashioned

    objLabel.Text = "<LABEL for='" & objTextBox.ClientID & "'>Name
    Column</LABEL>"

    lemmie know how it works out

    -- a --
    addup, Jun 22, 2006
    #7
  8. Corey B

    Corey B Guest

    addup wrote:
    > There's something wrong, since it doesn't work :)
    >
    > You are correct, it should be ID, not ClientID, but that's not the
    > answe either
    >
    > Here's what i would do to trace the problem/s
    > 1. comment out the objLabel.AssociatedControlID = objTextBox.ID line
    > 2. Check the HTML rendering of the datagridgrid. Confirm that
    > 'grdMyGrid__ctl2_txtFoot' is the clien-side id/name of the footer text
    > box
    > 3. And the kicker - * don't * use AssociatedControlID, try the
    > old-fashioned
    >
    > objLabel.Text = "<LABEL for='" & objTextBox.ClientID & "'>Name
    > Column</LABEL>"
    >
    > lemmie know how it works out
    >
    > -- a --


    Well it sorta works. The problem is that when you just set the
    Label.Text property like you suggested then ASP.NET emits a SPAN tag
    around the LABEL tag. I'm not sure, but I think that is not strictly
    508 compliant.

    I am getting the feeling that when I use the AssociatedControlID
    property that ASP.NET is expecting that the label and the associated
    control will be in the same container. Is it possible that because the
    Label is in the Header of a DataGrid and the text box is in the Footer
    of a DataGrid that they can't properly reference each other?

    For now I have figured out a work around. I have decided not to have
    the column header be the label. I will create individual labels for
    each textbox. I will just use CSS to make them hidden so that sighted
    users don't see them, but text readers will read them. I have tested
    this and it works fine.

    Thanks for the help. I have read that in ASP.NET v2.0 that they have
    improved 508 compliant output.

    Corey
    Corey B, Jun 22, 2006
    #8
  9. Corey B

    addup Guest

    Corey B wrote:
    > addup wrote:
    > > There's something wrong, since it doesn't work :)
    > >
    > > You are correct, it should be ID, not ClientID, but that's not the
    > > answe either
    > >
    > > Here's what i would do to trace the problem/s
    > > 1. comment out the objLabel.AssociatedControlID = objTextBox.ID line
    > > 2. Check the HTML rendering of the datagridgrid. Confirm that
    > > 'grdMyGrid__ctl2_txtFoot' is the clien-side id/name of the footer text
    > > box
    > > 3. And the kicker - * don't * use AssociatedControlID, try the
    > > old-fashioned
    > >
    > > objLabel.Text = "<LABEL for='" & objTextBox.ClientID & "'>Name
    > > Column</LABEL>"
    > >
    > > lemmie know how it works out
    > >
    > > -- a --

    >
    > Well it sorta works. The problem is that when you just set the
    > Label.Text property like you suggested then ASP.NET emits a SPAN tag
    > around the LABEL tag. I'm not sure, but I think that is not strictly
    > 508 compliant.
    >
    > I am getting the feeling that when I use the AssociatedControlID
    > property that ASP.NET is expecting that the label and the associated
    > control will be in the same container. Is it possible that because the
    > Label is in the Header of a DataGrid and the text box is in the Footer
    > of a DataGrid that they can't properly reference each other?
    >
    > For now I have figured out a work around. I have decided not to have
    > the column header be the label. I will create individual labels for
    > each textbox. I will just use CSS to make them hidden so that sighted
    > users don't see them, but text readers will read them. I have tested
    > this and it works fine.
    >
    > Thanks for the help. I have read that in ASP.NET v2.0 that they have
    > improved 508 compliant output.
    >
    > Corey


    That's easy enough to fix ...

    Remove the label from your headertemplate (heck, remove the
    headertemplate altogether!) and then,

    Static tdHeader As WebControls.TableCell
    Dim objTextBox As HtmlControls.HtmlInputText

    Select Case e.Item.ItemType
    Case ListItemType.Header
    tdHeader = e.Item.Cells(0) '.FindControl("lblHeaderLabel")
    Case ListItemType.Footer
    objTextBox = e.Item.FindControl("txtFoot")
    If Not tdHeader Is Nothing AndAlso _
    Not objTextBox Is Nothing Then
    tdHeader.Text = "<LABEL for='" & objTextBox.ClientID &
    "'>Name</LABEL>"
    End If
    End Select


    I said easy, not pretty :)

    Once you are confident this works for you, you may think of
    generalizing it; create your custom column, inherited from
    bound/template column as required.

    It's not always easy to extend the asp.net datagrid, but the rewards
    are often worth the effort.

    -- a --
    addup, Jun 22, 2006
    #9
  10. Corey B

    Corey B Guest

    addup wrote:
    > That's easy enough to fix ...
    >
    > Remove the label from your headertemplate (heck, remove the
    > headertemplate altogether!) and then,
    >
    > Static tdHeader As WebControls.TableCell
    > Dim objTextBox As HtmlControls.HtmlInputText
    >
    > Select Case e.Item.ItemType
    > Case ListItemType.Header
    > tdHeader = e.Item.Cells(0) '.FindControl("lblHeaderLabel")
    > Case ListItemType.Footer
    > objTextBox = e.Item.FindControl("txtFoot")
    > If Not tdHeader Is Nothing AndAlso _
    > Not objTextBox Is Nothing Then
    > tdHeader.Text = "<LABEL for='" & objTextBox.ClientID &
    > "'>Name</LABEL>"
    > End If
    > End Select
    >
    >
    > I said easy, not pretty :)
    >
    > Once you are confident this works for you, you may think of
    > generalizing it; create your custom column, inherited from
    > bound/template column as required.
    >
    > It's not always easy to extend the asp.net datagrid, but the rewards
    > are often worth the effort.
    >
    > -- a --


    Thanks. That did the trick. I just needed to think outside the box a
    little bit. Thanks again for your help.

    Corey
    Corey B, Jun 22, 2006
    #10
  11. Corey B

    Alan Silver Guest

    In article <>,
    addup <> writes
    >objLabel.Text = "<LABEL for='" & objTextBox.ClientID & "'>Name
    >Column</LABEL>"


    Actually, a more robust way to do this is the following HTML:

    <label for="<%= objTextBox.ClientID %>">Name</label>

    HTH

    --
    Alan Silver
    (anything added below this line is nothing to do with me)
    Alan Silver, Jun 27, 2006
    #11
    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. =?Utf-8?B?Zm1AbmV3c2dyb3Vwcy5ub3NwYW0=?=

    508 compliant (i.e. accessible to the people with disabilities)?

    =?Utf-8?B?Zm1AbmV3c2dyb3Vwcy5ub3NwYW0=?=, Nov 4, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    486
    Steven Cheng[MSFT]
    Nov 8, 2004
  2. VBDotNETCoder

    508 Compliancy Tools for ASP.NET

    VBDotNETCoder, Nov 15, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    419
    Kevin Spencer
    Nov 16, 2004
  3. wahtnamas
    Replies:
    0
    Views:
    880
    wahtnamas
    May 1, 2009
  4. otto

    Ajax and 508 Compliance

    otto, Mar 17, 2005, in forum: Javascript
    Replies:
    2
    Views:
    75
  5. kampy
    Replies:
    9
    Views:
    318
    Steven D'Aprano
    Oct 19, 2012
Loading...

Share This Page