65.9K
CodeProject 正在变化。 阅读更多。
Home

使用箭头(上/下)键进行 GridView 行导航

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (36投票s)

2008 年 4 月 29 日

CPOL

3分钟阅读

viewsIcon

175612

downloadIcon

2523

本文介绍如何使用 JavaScript 借助箭头(上/下)键来导航 GridView 行。

demo.gif

引言

在 IE 中使用箭头(上/下)键实现 GridView 行导航是一项简单的任务,但在其他浏览器中则有些棘手。最初,我编写的 JavaScript 代码在 IE 中运行良好,但在其他浏览器中却不行。在网上进行了大量研究后,我从 Mozilla Development Center 网站 [^] 学到了一些技巧,以便让此脚本在其他浏览器上运行。

使用此脚本,您可以使用箭头(上/下)键导航 GridView 行,但导航之前,您必须先使用鼠标 onclick 事件选择一行。

HTML 代码

以下是此演示中 GridView 的 HTML 代码

<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" 
              OnRowCreated="gridView_RowCreated"
              TabIndex="0" GridLines="Horizontal">
   <Columns>
      <asp:BoundField HeaderText="S#" DataField="sno">
         <HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="50px" />
         <ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="50px" />
      </asp:BoundField>
      <asp:BoundField HeaderText="Random No" DataField="rndno">
         <HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="150px" />
         <ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="150px" />
      </asp:BoundField>
      <asp:BoundField HeaderText="Date" DataField="date">
         <HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
         <ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
      </asp:BoundField>
      <asp:BoundField HeaderText="Time" DataField="time">
         <HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
         <ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Width="100px" />
      </asp:BoundField>
   </Columns>
   <RowStyle BackColor="#FFE0C0" />
   <HeaderStyle BackColor="#FF8000" Font-Bold="True" ForeColor="White" />
   <AlternatingRowStyle BackColor="#FFC080" />
</asp:GridView>

在此演示中,GridView 的行为方式如同一个 TabIndex 等于 0 的组件。

C# 代码

以下是 GridViewRowCreated 事件的 C# 代码

 if (e.Row.RowType == DataControlRowType.DataRow && 
    (e.Row.RowState == DataControlRowState.Normal || 
     e.Row.RowState == DataControlRowState.Alternate))
 {
     e.Row.TabIndex = -1;
     e.Row.Attributes["onclick"] = 
       string.Format("javascript:SelectRow(this, {0});", e.Row.RowIndex);
     e.Row.Attributes["onkeydown"] = "javascript:return SelectSibling(event);";
     e.Row.Attributes["onselectstart"] = "javascript:return false;";
 }

在上面的代码中,首先确保该行是 NormalAlternate。然后,在 GirdView 的每一行上附加了客户端事件 onclickonkeydownonselectstart。另外,请注意,GirdView 的每一行都已设置为 TabIndex 等于 -1,以便以编程方式将焦点设置在其上。实际上,在此示例中,GridView 的行为方式如同一个 TabIndex = 0 的组件,而 GridView 的每一行则表现得像组件中 TabIndex = -1 的元素。通过箭头键进行组件中每个元素的导航。当用户通过箭头(上/下)键导航到某一行时,该行就会获得焦点。通过在 GridView 的每一行上关联 onkeydown 事件来实现对箭头键的支持。

在捕获按键事件时,重要的是阻止浏览器执行按键的默认行为。按下向上/向下箭头键产生的常见浏览器行为是滚动文档。如果您希望捕获箭头键并使用它们将焦点更改到不同的 GridView 行,则需要阻止默认的滚动行为。这可以通过将事件的返回值设置为 false 来实现。请注意 onkeydown 事件是如何在行上附加的。

onclick 事件用于通过鼠标选择一行。在使用箭头(上/下)键导航 GridView 行之前,我们必须先使用鼠标 onclick 事件选择一行。

onselectstart 事件用于在使用鼠标选择 GridView 行时,阻止单元格文本被选中。

JavaScript代码

<script type="text/javascript">
    var SelectedRow = null;
    var SelectedRowIndex = null;
    var UpperBound = null;
    var LowerBound = null;
    
    window.onload = function()
    {
        UpperBound = parseInt('<%= this.gridView.Rows.Count %>') - 1;
        LowerBound = 0;
        SelectedRowIndex = -1;        
    }
    
    function SelectRow(CurrentRow, RowIndex)
    {        
        if(SelectedRow == CurrentRow || RowIndex > UpperBound || RowIndex < LowerBound)
            return;
         
        if(SelectedRow != null)
        {
            SelectedRow.style.backgroundColor = SelectedRow.originalBackgroundColor;
            SelectedRow.style.color = SelectedRow.originalForeColor;
        }
        
        if(CurrentRow != null)
        {
            CurrentRow.originalBackgroundColor = CurrentRow.style.backgroundColor;
            CurrentRow.originalForeColor = CurrentRow.style.color;
            CurrentRow.style.backgroundColor = '#DCFC5C';
            CurrentRow.style.color = 'Black';
        } 
        
        SelectedRow = CurrentRow;
        SelectedRowIndex = RowIndex;
        setTimeout("SelectedRow.focus();",0); 
    }
    
    function SelectSibling(e)
    { 
        var e = e ? e : window.event;
        var KeyCode = e.which ? e.which : e.keyCode;
        
        if(KeyCode == 40)
            SelectRow(SelectedRow.nextSibling, SelectedRowIndex + 1);
        else if(KeyCode == 38)
            SelectRow(SelectedRow.previousSibling, SelectedRowIndex - 1);
            
        return false;
    }
    </script>

在上面的脚本中,全局变量已在 window.onload 事件中初始化。有两个函数:SelectRowSelectSibling。当我们在 GridView 行上单击时,或者通过 keydownkeyup 事件响应调用 SelectSibling 方法时,将调用 SelectRow。当我们按下向上或向下箭头键时,将调用 SelectSibling 方法。此方法会使用适当的参数调用 SelectRow 方法。在 SelectRow 函数中,如果当前行是前一个选定的行,或者 RowIndex 不在 LowerBoundUpperBound 之间,则不执行任何操作;否则,它会恢复前一个选定行的状态,并更改当前选定行的状态。之后,变量 SelectedRowSelectedRowIndex 的值会相应更改,并使用 setTimeout 方法将焦点设置到当前选定的行上。在 IE 和 Mozilla 中都需要此超时,以防止用户单击按钮和其他控件时,脚本出现意外的异常行为。

结论

我已尽最大努力使此代码无错误。非常欢迎对代码提出进一步改进的建议和批评。

浏览器兼容性

我已在各种浏览器上测试过此代码,运行效果良好。下面是测试过的浏览器及其版本的列表

Browsers.png

此代码目前在 Opera(9.27 的早期版本)、Safari、Firebox(1.0 版本)以及 Mozilla 的旧版本(1.7 及更早版本)上可能无法正常工作,因为某些浏览器不支持对所有元素都支持的 TabIndex 属性等新功能。

© . All rights reserved.