This is a migrated thread and some comments may be shown as answers.

Section 508 and WCAG Complaince for RadGrid

2 Answers 61 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Ken Lassesen
Top achievements
Rank 2
Ken Lassesen asked on 19 Feb 2010, 01:13 PM

Requirements

RadControls version

2009Q3

.NET version

ALL

Visual Studio version

ALL

programming language

C#

browser support

all browsers supported by RadControls


PROJECT DESCRIPTION

A strategy for building a Section 508/WCAG Telerik radGrid page

Accessibility and translations can often result in a medusa head for code. On one hand you want a feature rich grid but you are constrained by Section 508.  Managing and tracking resource mnemonic across a large project becomes a nightmare (and very very boring code typing for developers which usually impacts quality control).  Another pain with a large site is consistency of presentation.

 

What if I claim that all you need to do is toss the code below into a page and be done with coding!

 

The Web Page Content:

   1: <telerik:RadGrid runat="server" ID="AccountSummaryGrid" DataSourceID="AccountSummaryDb" AccessKey="X">
   2:     <MasterTableView AutoGenerateColumns="false" DataKeyNames="AccountName">
   3:         <Columns>
   4:             <telerik:GridBoundColumn DataField="AccountName" UniqueName="Grid_AccountName">
   5:             </telerik:GridBoundColumn>
   6:             <telerik:GridBoundColumn DataField="Description" UniqueName="Grid_AccountDescription">
   7:             </telerik:GridBoundColumn>
   8:             <telerik:GridBoundColumn DataField="Balance" UniqueName="Grid_AccountBalance">
   9:             </telerik:GridBoundColumn>
  10:             <telerik:GridBoundColumn DataField="CreditLimit" UniqueName="Grid_AccountCreditLimit">
  11:             </telerik:GridBoundColumn>
  12:             <telerik:GridBoundColumn DataField="OwnershipType" UniqueName="Grid_OwnershipType">
  13:             </telerik:GridBoundColumn>
  14:         </Columns>
  15:     </MasterTableView>
  16: </telerik:RadGrid>

With the page behind code being a horrible:

   1: protected void Page_Load(object sender, EventArgs e)
   2: { 
   3:     RadGridUtilities.ApplyDefaultSettings(AccountSummaryGrid);
   4: }

There are many tricks (and enhancement not shown), but the first item is to give the user the option to put the site into Accessibility Mode. If you give that option then only the pages while in Accessibility Mode must comply with Section 508. You can be as feature rich as you want elsewhere!!

 

This is what the one C# statement above does.

  • Provide web site defaults to the grid (every grid…), you want the defaults changed – it occurs in one spot only not in 100 pages!
  • Provide translation that is based off of the Control.Id (SO no more “Button1” but descriptive “ButtonToRetrieveStatement”
  • Modify the grid for what you want to do for accessibility.

There are a few items that I excluded (like automatically creating Resx entries for every phrase dynamically and self-auditing for 508 compliance) so the code is clearer.

/// <summary>
/// Applies the default settings to the page. If user customization is implemented
/// the settings here would come from their preferences stored in a Session object.
/// </summary>
/// <param name="grid">a radGrid control</param>
/// <param name="onGetOnly">Determines if the settings are down on every postback or only on first GET</param>
public static void ApplyDefaultSettings(RadGrid grid, bool onGetOnly)
{
    // Uniquenames should have an underscore (_) in it. grid_ is the recommended prefix so that
    //localization may identify items used in grids
    char[] sepUnique = { '_', ' ' };

    // Items requiring     
    grid.ItemCreated += grid_ItemCreatedAddRowScope;

    // Get translations. For items that Telerik may have translated use fallback version. 
    grid.MasterTableView.Caption = ResourceTranslation.TranslateField(string.Format(CultureInfo.CurrentCulture, "%ContentPage%{0}_Caption%", grid.ID));
    grid.MasterTableView.CommandItemSettings.AddNewRecordText = ResourceTranslation.TranslateField("%MasterPage%Grid_AddNewRecordText%", grid.MasterTableView.CommandItemSettings.AddNewRecordText);
    grid.MasterTableView.CommandItemSettings.ExportToCsvText = ResourceTranslation.TranslateField("%MasterPage%Grid_ExportToCsvText%", grid.MasterTableView.CommandItemSettings.ExportToCsvText);
    grid.MasterTableView.CommandItemSettings.ExportToExcelText = ResourceTranslation.TranslateField("%MasterPage%Grid_ExportToExcelText%", grid.MasterTableView.CommandItemSettings.ExportToExcelText);
    grid.MasterTableView.CommandItemSettings.ExportToPdfText = ResourceTranslation.TranslateField("%MasterPage%Grid_ExportToPdfText%", grid.MasterTableView.CommandItemSettings.ExportToPdfText);
    grid.MasterTableView.CommandItemSettings.ExportToWordText = ResourceTranslation.TranslateField("%MasterPage%Grid_ExportToWordText%", grid.MasterTableView.CommandItemSettings.ExportToWordText);
    grid.MasterTableView.CommandItemSettings.RefreshText = ResourceTranslation.TranslateField("%MasterPage%Grid_RefreshText%", grid.MasterTableView.CommandItemSettings.RefreshText);
    grid.MasterTableView.CssClass = ResourceTranslation.TranslateField("%MasterPage%Grid_CssClass%", grid.MasterTableView.CssClass);
    grid.MasterTableView.Summary = ResourceTranslation.TranslateField(string.Format(CultureInfo.CurrentCulture, "%ContentPage%{0}_Summary%", grid.ID));

    // This section would be used if images are to be customized for languages (unlikely)
    //    grid.MasterTableView.CommandItemSettings.AddNewRecordImageUrl = ResourceTranslation.TranslateField(grid.MasterTableView.CommandItemSettings.AddNewRecordImageUrl);
    //    grid.MasterTableView.CommandItemSettings.ExportToCsvImageUrl = ResourceTranslation.TranslateField(grid.MasterTableView.CommandItemSettings.ExportToCsvImageUrl);
    //    grid.MasterTableView.CommandItemSettings.ExportToExcelImageUrl = ResourceTranslation.TranslateField(grid.MasterTableView.CommandItemSettings.ExportToExcelImageUrl);
    //    grid.MasterTableView.CommandItemSettings.ExportToPdfImageUrl = ResourceTranslation.TranslateField(grid.MasterTableView.CommandItemSettings.ExportToPdfImageUrl);
    //    grid.MasterTableView.CommandItemSettings.ExportToWordImageUrl = ResourceTranslation.TranslateField(grid.MasterTableView.CommandItemSettings.ExportToWordImageUrl);
    
    // Site specific options. 
    // If User Options are allowed, the user's setting would be assigned instead.
    grid.AllowPaging = true;
    grid.AllowSorting = true;
    grid.ExportSettings.FileName = grid.ID;
    grid.ExportSettings.IgnorePaging = true;
    grid.ExportSettings.OpenInNewWindow = true;
    grid.ExportSettings.Pdf.Author = "Lassesen Consulting, LLC";
    grid.ExportSettings.Pdf.PageTitle = grid.MasterTableView.Caption;
    grid.ExportSettings.Pdf.Subject = grid.ID;
    grid.MasterTableView.AllowPaging = true;
    grid.MasterTableView.AllowSorting = true;
    grid.MasterTableView.CommandItemDisplay = GridCommandItemDisplay.TopAndBottom;
    grid.MasterTableView.CommandItemSettings.ShowExportToCsvButton = true;
    grid.MasterTableView.CommandItemSettings.ShowExportToExcelButton = true;
    grid.MasterTableView.CommandItemSettings.ShowExportToPdfButton = true;
    grid.MasterTableView.CommandItemSettings.ShowExportToWordButton = true;
    grid.MasterTableView.PagerStyle.Mode = GridPagerMode.NextPrevNumericAndAdvanced;
    grid.PageSize = 60;

    // Changes for accessibility on a Grid Level
    // Remember hanidcap can be cognitive or physical -- so trim lots
    // of features
    if (Section508.UserSetting)
    {
        grid.AllowCustomPaging = false;
        grid.AllowFilteringByColumn = false;
        grid.AllowMultiRowEdit = false;
        grid.AllowMultiRowSelection = false;
        grid.MasterTableView.AllowPaging = false;
        grid.MasterTableView.AllowSorting = false;
        grid.MasterTableView.CommandItemDisplay = GridCommandItemDisplay.None;
        grid.MasterTableView.CommandItemSettings.ShowExportToCsvButton = false;
        grid.MasterTableView.CommandItemSettings.ShowExportToExcelButton = false;
        grid.MasterTableView.CommandItemSettings.ShowExportToPdfButton = false;
        grid.MasterTableView.CommandItemSettings.ShowExportToWordButton = false;
        grid.MasterTableView.ShowGroupFooter = false;
        grid.ShowGroupPanel = false;
        grid.ShowStatusBar = false;
    }

    int colNo = 0;
    foreach (GridColumn col in grid.MasterTableView.Columns)
    {
        // uniquekeys are assumed to be compounded with an underscore
        //separator. Only last part is used as HeaderAbbr
        var translationkey = col.UniqueName;
        var parts = col.UniqueName.Split(sepUnique, System.StringSplitOptions.RemoveEmptyEntries);
        col.HeaderAbbr = parts[parts.Length - 1];
        // CHANGES for Accessibilty at a Column Level
        if (Section508.UserSetting)
        {
            col.AutoPostBackOnFilter = false;
            col.Groupable = false;
            col.HeaderButtonType = GridHeaderButtonType.PushButton;
            col.Resizable = false;
        }
        string tooltipMnemonic = string.Empty;
        //Determine if sortable and adopt appropriate tooltip
        if (grid.AllowSorting)
        {            
            if (! string.IsNullOrEmpty(col.SortExpression))
            {
                tooltipMnemonic = "Sort";
            }
            tooltipMnemonic =string.Format(CultureInfo.CurrentCulture, "%ContentPage%{0}_{1}Tooltip%", translationkey,tooltipMnemonic);
            col.HeaderTooltip = ResourceTranslation.TranslateField(tooltipMnemonic);
        }
        col.HeaderText = ResourceTranslation.TranslateField(string.Format(CultureInfo.CurrentCulture, "%ContentPage%{0}%", translationkey));
    }
}

 

The first item of importance is the event handler that is added

grid.ItemCreated += grid_ItemCreatedAddRowScope;

 

Grids require at least one <td scope=”row”> for Section 508 which is not natively provided by Telerik, so we must add it while the item is being created. This is done with the code below. The columns are those that are in the DataKeyNames, which makes it almost happens by designed-accident.

   1: /// <summary>
   2: /// Routine to add scope="row" to the grid for 508 compliance. The items are those specified in
   3: /// DataKeyNames
   4: /// </summary>
   5: /// <param name="sender">a telerik radgrid control</param>
   6: /// <param name="e"></param>
   7: static void grid_ItemCreatedAddRowScope(object sender, GridItemEventArgs e)
   8: {
   9:     if (e.Item is GridDataItem)
  10:     {
  11:         GridDataItem dataItem = e.Item as GridDataItem;
  12:         foreach (string key in dataItem.OwnerTableView.DataKeyNames)
  13:         {
  14:             foreach (GridColumn col in dataItem.OwnerTableView.Columns)
  15:             {
  16:                 if (col.IsBoundToFieldName(key))
  17:                 {
  18:                     TableCell cell = dataItem[col.UniqueName];
  19:                     cell.Attributes["scope"] = "row";
  20:                 }
  21:             }
  22:         }
  23:     }
  24: }

 

The other item is the ResourceTranslation.TranslateField which is a widget between the code and the usual handling of resources. It allows me to identify if a resource is missing as well as do some fancy stuff like “lookup the term and if you do not find it, then use what Telerik provides”;

 

That’s it.


From one of my blogs, http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/

2 Answers, 1 is accepted

Sort by
0
Yavor
Telerik team
answered on 24 Feb 2010, 08:48 AM
Hello Ken,

Thank you for posting your implementation to the public. I have transferred the code library entry to a forum post, so that other community members can benefit from it as well. Your Telerik points have been updated for your involvement. Thank you for your contribution.

Regards,
Yavor
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Mark Galbreath
Top achievements
Rank 2
answered on 24 Feb 2010, 02:46 PM
A most excellent post, Ken!  Thanks for sharing!

Cheers!
Mark
Tags
Grid
Asked by
Ken Lassesen
Top achievements
Rank 2
Answers by
Yavor
Telerik team
Mark Galbreath
Top achievements
Rank 2
Share this question
or