![]() |
|
|
|||||||
![]() |
ASP Net - How to create section 508 compliant Data Grid - ASP.NET v1.1 |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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 |
|
|
|
|
#2 |
|
Posts: n/a
|
"Corey B" <> wrote in message news: ups.com... > 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 |
|
|
|
#3 |
|
Posts: n/a
|
vMike wrote:
> "Corey B" <> wrote in message > news: ups.com... > > 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>…</ITEMTEMPLATE> <EDITITEMTEMPLATE>…</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 |
|
|
|
#4 |
|
Posts: n/a
|
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>…</ITEMTEMPLATE> > <EDITITEMTEMPLATE>…</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>…</ITEMTEMPLATE> <EDITITEMTEMPLATE>…</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 |
|
|
|
#5 |
|
Posts: n/a
|
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>…</ITEMTEMPLATE> > > <EDITITEMTEMPLATE>…</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>…</ITEMTEMPLATE> > <EDITITEMTEMPLATE>…</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 |
|
|
|
#6 |
|
Posts: n/a
|
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 |
|
|
|
#7 |
|
Posts: n/a
|
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 |
|
|
|
#8 |
|
Posts: n/a
|
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 |
|
|
|
#9 |
|
Posts: n/a
|
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 |
|
|
|
#10 |
|
Posts: n/a
|
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 |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How to burn copy CD/DVD and create Data/Audio/Video Disc? | dvdloveri | Software | 6 | 07-27-2009 07:58 AM |
| how to create an new webform with codebehind dynamically using c# in asp.net?. | krish200 | Software | 1 | 12-18-2007 09:16 PM |
| asp.net : custom code to delete data from Grid view (Database) | sara_23apr | Software | 1 | 06-19-2007 01:08 PM |
| Unable to create ASP.NET application | SHARP END | Software | 0 | 04-04-2007 10:54 PM |
| Create .EPS Image With ASP.NET (Using C#.NET) | sovan | Software | 0 | 07-06-2006 09:29 AM |