[ASP.net] 撰寫無障礙網頁的ASP.net技巧&分享 (.net 4)

[ASP.net] 撰寫無障礙網頁的ASP.net技巧&分享

臺灣應該有不少Web開發者經常要撰寫行政院研考會規定的無障礙網頁

個人本身也常上網找ASP.net某個Server Control要如何撰寫才能通過無障礙標準,但這類文章很難找出個整理

所以此篇是獻給那些Web開發者們,在開發ASP.net程式時,有個參考指南(如果不曉得什麼是無障礙網頁,有興趣的人可以點選這裡)

本文以通過A+無障礙機器(FreeGo軟體掃描)檢測為主(以下簡稱A+)

要通過A+,跟ASP.net控制項有關的兩個原則:

1.<img />要有alt

2.各HTML Tag若有滑鼠事件,則要有對應的鍵盤事件

例如:onClick=>onKeyPress、onMouseOver=>onFocus、onMouseOut=>onBlur、onMouseDown=>onKeyDown、onMouseUp=>onKeyUp

看似簡單,但實際情況是,微軟有些控制項註定過不了無障礙標準或者加了AutoPostBack屬性後就無法通過

MSDN上針對無障礙網頁的一些說明:

ASP.NET 中的網頁可及性支援ASP.NET 控制項和網頁可及性

以下針對常用到的ASP.net Server Control說明,呈現出HTML的Tag及該如何撰寫才能通過A+方法做些整理

(另外,講白一件事,能通過無障礙標準的網站,其實未必真的是無障礙網站XD)

 

文章很長,如果想快速5分鐘上手的話,建議速讀紅色部份就好,其他都是我在Try-Error證明該控制項過不過得了無障礙標準。

 

 

1. Label

ASP.net伺服器標記

<asp:Label ID="Label1"  runat="server" Text="A" />

呈現的HTML

<span id="Label1">A</span> 

 

2. Literal

ASP.net伺服器標記

<asp:Literal ID="Literal1" Text="A" runat="server" />

呈現的HTML:無

說明:如果一般要套美工人員版型的話,個人推薦用Literal,最能符合美工人員給的HTML版型

除非需要很多屬性輔助撰寫程式才用到Label,例如在GridView(或ListView)的資料繫結中,個人常會這樣寫

<asp:Label id=”lb_myLabel” runat=”server” Text=’<%# Eval(“欄位1”)%>’ ToolTip=’<%# Eval(“欄位2”)%>’ />

然後在GridView的RowDataBound事件,我就可以抓到該列欄位1和欄位2的值了。

這兩個控制項通常用來手寫HTML用,把握A+無障礙原則的話,要通過應該不難。

 

3. Image

ASP.net伺服器標記

<asp:Image ID="Image1" runat="server" AlternateText="必填alt" ImageUrl="images/Source.jpg" BorderWidth="0" />

呈現的HTML

<img id="Image1" src="images/Source.jpg" alt="必填alt" style="border-width:0px;" />

說明:要加上AlternateText屬性,才能通過。

如果要做滑鼠滑過置換圖片的效果,請參考以下寫法:

<asp:Image AlternateText="Alt必填" ImageUrl="原始圖片Url" onmouseout='this.src="原始圖片Url"' onblur='this.src="原始圖片Url"' onmouseover='this.src="置換圖片Url"' onfocus='this.src="置換圖片Url"' runat="server"/>

若在C# Code-Behind中,this.src=””雙引號要加 \ 跳脫字元。

2011.9.30 追加發現:即使沒有加BorderWidth屬性,呈現出的Html會加style="border-width:0px;"

 

 

4. HyperLink

ASP.net伺服器標記

<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="http://www.google.com.tw" Target="_blank" Text="文字"
     ToolTip="ToolTip會變成title">HyperLink Tag中間的文字</asp:HyperLink> 

(像以上同時指定Text又Tag間包住文字,則Tag之間的文字會優先)

呈現的HTML

<a id="HyperLink1" title="ToolTip會變成title" href="http://www.google.com.tw" target="_blank">HyperLink Tag中間的文字</a>

說明:基本上可以通過A+,但該注意的是,不能加ImageUrl屬性,HyperLink的ToolTip呈現出HTML的為<a title=””></a>,如果指定了ImageUrl,就無法為那張圖片指定alt

所以想要超連結包住圖片,正確寫法:

<asp:HyperLink ID="lnk" NavigateUrl="Url位址"  runat="server" >
          <asp:Image ID="img" ImageUrl="圖片Url" AlternateText="圖片說明文字必填" runat="server" />
</asp:HyperLink>

或用Literal控制項手寫HTML

<a href="Url位址">
  <img src="圖片Url" alt="圖片說明文字必填" />
</a>

 

5. DropDownList

說明:如果加上AutoPostBack屬性,則HTML Tag會多加onchange事件,不過仍可以通過A+,請安心服用。

呈現的HTML

<select name="DropDownList1" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;DropDownList1\&#39;,\&#39;\&#39;)&#39;, 0)" id="DropDownList1">
      <option selected="selected" value="a">a</option>
      <option value="b">b</option>
      <option value="c">c</option>
</select>

 

6. RadioButton

ASP.net伺服器標記

<asp:RadioButton ID="rdo_A" Text="A" GroupName="group" runat="server" />
<asp:RadioButton ID="rdo_B" Text="B" GroupName="group" runat="server" />

 

呈現的HTML

<input id="rdo_A" type="radio" name="group" value="rdo_A" /><label for="rdo_A">A</label>
<input id="rdo_B" type="radio" name="group" value="rdo_B" /><label for="rdo_B">B</label>

 

若加上AutoPostBack屬性

<asp:RadioButton ID="rdo_A" Text="A" GroupName="group" AutoPostBack="true" runat="server" OnCheckedChanged="rdo_A_CheckedChanged" />
<asp:RadioButton ID="rdo_B" Text="B" GroupName="group" AutoPostBack="true" runat="server" OnCheckedChanged="rdo_B_CheckedChanged" />

呈現的HTML,<input>會自動加上onclick事件

<input id="rdo_A" type="radio" name="group" value="rdo_A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_A\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="rdo_A">A</label>
<input id="rdo_B" type="radio" name="group" value="rdo_B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_B\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="rdo_B">B</label>

嘗試為<input>加onkeypress鍵盤事件

    protected void Page_Load(object sender, EventArgs e)
    {
       
            rdo_A.Attributes["onkeypress"] = "rdo_A_onkeypress();";
            rdo_B.Attributes["onkeypress"] = "rdo_B_onkeypress();";
        
    }

呈現的HTML

<span onkeypress="rdo_A_onkeypress();"><input id="rdo_A" type="radio" name="group" value="rdo_A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_A\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="rdo_A">A</label></span>
<span onkeypress="rdo_B_onkeypress();"><input id="rdo_B" type="radio" name="group" value="rdo_B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_B\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="rdo_B">B</label></span>
        

2011.7.2 追記 嘗試為<input>加onkeypress鍵盤事件

    protected void Page_Load(object sender, EventArgs e)
    {
        rdo_A.InputAttributes["onkeypress"] = "rdo_A_onkeypress();";

        rdo_B.InputAttributes["onkeypress"] = "rdo_B_onkeypress();"; 


    }

呈現的HTML

<input id="rdo_A" type="radio" name="group" value="rdo_A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_A\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="rdo_A_onkeypress();" /><label for="rdo_A">A</label> 

<input id="rdo_B" type="radio" name="group" value="rdo_B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;rdo_B\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="rdo_B_onkeypress();" /><label for="rdo_B">B</label>

結論:RadioButton加上AutoPostBack後,須在InputAttributes加上onkeypress事件才可過A+。

 

7. RadioButtonList

ASP.net伺服器標記

<asp:RadioButtonList ID="RadioButtonList1" runat="server">
            <asp:ListItem>A</asp:ListItem>
            <asp:ListItem>B</asp:ListItem>
            <asp:ListItem>C</asp:ListItem>
</asp:RadioButtonList>

呈現的HTML

<table id="RadioButtonList1">
	<tr>
		<td><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="A" /><label for="RadioButtonList1_0">A</label></td>
	</tr><tr>
		<td><input id="RadioButtonList1_1" type="radio" name="RadioButtonList1" value="B" /><label for="RadioButtonList1_1">B</label></td>
	</tr><tr>
		<td><input id="RadioButtonList1_2" type="radio" name="RadioButtonList1" value="C" /><label for="RadioButtonList1_2">C</label></td>
	</tr>
</table>

若加上AutoPostBack屬性

<asp:RadioButtonList ID="RadioButtonList1" runat="server" AutoPostBack="True" 
            onselectedindexchanged="RadioButtonList1_SelectedIndexChanged">
            <asp:ListItem>A</asp:ListItem>
            <asp:ListItem>B</asp:ListItem>
            <asp:ListItem>C</asp:ListItem>
</asp:RadioButtonList>

 

呈現的HTML,<input>會自動加上onclick事件

<table id="RadioButtonList1" border="0">
	<tr>
	    <td><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_0">A</label></td>
	</tr><tr>
	    <td><input id="RadioButtonList1_1" type="radio" name="RadioButtonList1" value="B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_1">B</label></td>
	</tr>
                 <tr>
                     <td><input id="RadioButtonList1_2" type="radio" name="RadioButtonList1" value="C" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_2">C</label></td>
	</tr>
</table> 

嘗試為<input>加onkeypress鍵盤事件

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            RadioButtonList1.Attributes["onkeypress"] = "RadioButtonList1_onkeypress()";

            foreach (ListItem item in RadioButtonList1.Items)
            {
                item.Attributes["onkeypress"] = "ListItem_onkeypress()";
            }
        }
    }

    protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
    {
       
    }

呈現的HTML

  <table id="RadioButtonList1" onkeypress="RadioButtonList1_onkeypress()" border="0">
	<tr>
		<td><span onkeypress="ListItem_onkeypress()"><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_0">A</label></span></td>
	</tr>
	<tr>
		<td><span onkeypress="ListItem_onkeypress()"><input id="RadioButtonList1_1" type="radio" name="RadioButtonList1" value="B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_1">B</label></span></td>
	</tr>
	<tr>
		<td><span onkeypress="ListItem_onkeypress()"><input id="RadioButtonList1_2" type="radio" name="RadioButtonList1" value="C" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_2">C</label></span></td>
	</tr>
</table>

 

2011.7.2追記,嘗試抓出RadioButtonList裡的Controls再加上InputAttributes

 protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control c  in RadioButtonList1.Controls)
        {
            ((RadioButton)c).InputAttributes["onkeypress"] = "myKeyPress();";
        }


    }

呈現出的HTML

<table id="RadioButtonList1">
 <tr>
  <td><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="A" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_0">A</label></td>
 </tr><tr>
  <td><input id="RadioButtonList1_1" type="radio" name="RadioButtonList1" value="B" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_1">B</label></td>
 </tr><tr>
  <td><input id="RadioButtonList1_2" type="radio" name="RadioButtonList1" value="C" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;RadioButtonList1$2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="RadioButtonList1_2">C</label></td>
 </tr>
</table>

沒有出現myKeyPress();

結論:RadioButtonList預設可以通過A+,但加上AutoPostBack後因為onkeypress無法跟onclick在同一個Tag,所以會過不了A+。

RadioButtonList跟DropDownList同樣都是單選,如果需要AutoPostBack屬性來撈資料,可以考慮改用DropDownList替代。

8. CheckBox

ASP.net伺服器標記

<asp:CheckBox ID="CheckBox1"  Text="A" runat="server" />
<asp:CheckBox ID="CheckBox2"  Text="B" runat="server" /> 

呈現的HTML

 <input id="CheckBox1" type="checkbox" name="CheckBox1" /><label for="CheckBox1">A</label>
 <input id="CheckBox2" type="checkbox" name="CheckBox2" /><label for="CheckBox2">B</label> 

若加上AutoPostBack屬性

<asp:CheckBox ID="CheckBox1"  Text="A" runat="server" AutoPostBack="true" />
<asp:CheckBox ID="CheckBox2"  Text="B" runat="server" AutoPostBack="true"/>

呈現的HTML,<input>會自動加上onclick事件

<input id="CheckBox1" type="checkbox" name="CheckBox1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="CheckBox1">A</label>
<input id="CheckBox2" type="checkbox" name="CheckBox2" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="CheckBox2">B</label> 

嘗試對CheckBox加入onkeypress

protected void Page_Load(object sender, EventArgs e)
{
        CheckBox1.Attributes["onkeypress"] = "CheckBox1_onkeypress();";
        CheckBox2.Attributes["onkeypress"] = "CheckBox2_onkeypress();";
}

呈現的HTML

<span onkeypress="CheckBox1_onkeypress();"><input id="CheckBox1" type="checkbox" name="CheckBox1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox1\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="CheckBox1">A</label></span>
<span onkeypress="CheckBox2_onkeypress();"><input id="CheckBox2" type="checkbox" name="CheckBox2" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox2\&#39;,\&#39;\&#39;)&#39;, 0)" /><label for="CheckBox2">B</label></span> 

 

2011.7.2 嘗試對CheckBox加入InputAttributes

protected void Page_Load(object sender, EventArgs e)
    {

        CheckBox1.InputAttributes["onkeypress"] = "CheckBox1_onkeypress();";

        CheckBox2.InputAttributes["onkeypress"] = "CheckBox2_onkeypress();";

    }

呈現出的HTML

<input id="CheckBox1" type="checkbox" name="CheckBox1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox1\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="CheckBox1_onkeypress();" /><label for="CheckBox1">A</label> 

<input id="CheckBox2" type="checkbox" name="CheckBox2" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBox2\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="CheckBox2_onkeypress();" /><label for="CheckBox2">B</label>

結論:CheckBox加上AutoPostBack後,須加上InputAttributes才可過A+。

 

9. CheckBoxList

ASP.net伺服器標記

<asp:CheckBoxList ID="CheckBoxList1" runat="server">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
</asp:CheckBoxList>

呈現的HTML

<table id="CheckBoxList1">
    <tr>
        <td><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" value="A" /><label for="CheckBoxList1_0">A</label></td>
    </tr>
        <tr>
        <td><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" value="B" /><label for="CheckBoxList1_1">B</label></td>
    </tr>
</table> 

若加上AutoPostBack屬性

<asp:CheckBoxList ID="CheckBoxList1" runat="server" AutoPostBack="true">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
</asp:CheckBoxList>


呈現的HTML,<input>會自動加上onclick事件

<table id="CheckBoxList1">
    <tr>
        <td><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" value="A" /><label for="CheckBoxList1_0">A</label></td>
    </tr><tr>
        <td><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" value="B" /><label for="CheckBoxList1_1">B</label></td>
    </tr>
</table>

嘗試對CheckBoxList加入onkeypress

protected void Page_Load(object sender, EventArgs e)
{
        CheckBoxList1.Attributes["onkeypress"] = "CheckBoxList1_onkeypress()"; 

        foreach (ListItem item in CheckBoxList1.Items)
        {
            item.Attributes["onkeypress"] = "item_onkeypress();";
        }
}

呈現的HTML

<table id="CheckBoxList1" onkeypress="CheckBoxList1_onkeypress()">
    <tr>
        <td><span onkeypress="item_onkeypress();"><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" value="A" /><label for="CheckBoxList1_0">A</label></span></td>
    </tr><tr>
        <td><span onkeypress="item_onkeypress();"><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" value="B" /><label for="CheckBoxList1_1">B</label></span></td>
    </tr>
</table> 

 

2011.7.2嘗試對CheciBoxList裡的每個CheckBox加上InputAttributes

protected void Page_Load(object sender, EventArgs e)
{
        foreach (Control c in CheckBoxList1.Controls)
        {
            ((CheckBox)c).InputAttributes["onkeypress"] = "item_onkeypress();";
           

        }
}

呈現的HTML

<table id="CheckBoxList1">
 <tr>
  <td><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$0\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="item_onkeypress();" value="A" /><label for="CheckBoxList1_0">A</label></td>
 </tr><tr>
  <td><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" onclick="javascript:setTimeout(&#39;__doPostBack(\&#39;CheckBoxList1$1\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="item_onkeypress();" value="B" /><label for="CheckBoxList1_1">B</label></td>
 </tr>
</table>

結論:CheckBoxList加上AutoPostBack後須加上InputAttributes才可過A+。

2011.11.09 追記

RepeatLayout=”Flow”

 <asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatLayout="Flow">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
        <asp:ListItem>C</asp:ListItem>
   </asp:CheckBoxList>

呈現的Html(容器為span、換行使用<br/>)

  <span id="Span1">
        <input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" value="A" /><label
            for="CheckBoxList1_0">A</label><br />
        <input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" value="B" /><label
            for="CheckBoxList1_1">B</label><br />
        <input id="CheckBoxList1_2" type="checkbox" name="CheckBoxList1$2" value="C" /><label
            for="CheckBoxList1_2">C</label>
    </span>

RepeatLayout=”UnorderedList”

    <asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatLayout="UnorderedList">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
        <asp:ListItem>C</asp:ListItem>
    </asp:CheckBoxList>

 

呈現的Html(容器為ul、每個項目為li)

 <ul id="CheckBoxList1">
	<li><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" value="A" /><label for="CheckBoxList1_0">A</label></li>
	<li><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" value="B" /><label for="CheckBoxList1_1">B</label></li>
	<li><input id="CheckBoxList1_2" type="checkbox" name="CheckBoxList1$2" value="C" /><label for="CheckBoxList1_2">C</label></li>
 
</ul>

RepeatLayout=”OrderedList”

<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatLayout="OrderedList">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
        <asp:ListItem>C</asp:ListItem>
    </asp:CheckBoxList>

呈現的Html(容器為ol、每個項目為li)

  <ol id="CheckBoxList1">
	<li><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" value="A" /><label for="CheckBoxList1_0">A</label></li>
	<li><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1$1" value="B" /><label for="CheckBoxList1_1">B</label></li>
	<li><input id="CheckBoxList1_2" type="checkbox" name="CheckBoxList1$2" value="C" /><label for="CheckBoxList1_2">C</label></li>
 
</ol>
  

CheckBoxList預設的RepeatLayout為Table

 

10. ListBox

ASP.net伺服器標記

<asp:ListBox ID="ListBox1" runat="server">
      <asp:ListItem>A</asp:ListItem>
      <asp:ListItem>B</asp:ListItem>
      <asp:ListItem>C</asp:ListItem>
</asp:ListBox>

呈現的HTML

<select size="4" name="ListBox1" id="ListBox1">
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option> 
</select>

若加上AutoPostBack屬性

<asp:ListBox ID="ListBox1" runat="server" AutoPostBack="true">
        <asp:ListItem>A</asp:ListItem>
        <asp:ListItem>B</asp:ListItem>
        <asp:ListItem>C</asp:ListItem>
</asp:ListBox>

呈現的HTML

<select size="4" name="ListBox1" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;ListBox1\&#39;,\&#39;\&#39;)&#39;, 0)" id="ListBox1">
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>

多選的HTML

<select size="4" name="ListBox1" multiple="multiple" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;ListBox1\&#39;,\&#39;\&#39;)&#39;, 0)" id="ListBox1">
    <option selected="selected" value="A">A</option>
    <option selected="selected" value="B">B</option>
    <option selected="selected" value="C">C</option>
</select> 

結論:不管單選還是多選,ListBox都可以過A+,請安心服用。

 

11. TextBox

ASP.net伺服器標記

<asp:TextBox ID="TextBox1" Text="A" runat="server" />

呈現的HTML

<input name="TextBox1" type="text" value="A" id="TextBox1" /> 

2011.7.2 追記:加上AutoPostBack

<asp:TextBox ID="TextBox1" Text="A" runat="server" AutoPostBack="True" ontextchanged="TextBox1_TextChanged" />

呈現的HTML

<input name="TextBox1" type="text" value="A" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;TextBox1\&#39;,\&#39;\&#39;)&#39;, 0)" onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" id="TextBox1" />

結論:TextBox可以過A+

 

12. Button

2011.12.03 修改

ASP.net伺服器標記

 <!--UseSubmitBehavior預設"true"-->
    <asp:Button runat="server" ID="btn_submit"  Text="我是submit" 
         onclick="btn_submit_Click" />
 
    <asp:Button runat="server" ID="btn"  Text="我是真Button" UseSubmitBehavior="false" 
         onclick="btn_Click" />

呈現的HTML

<!--UseSubmitBehavior預設"true"-->
    <input type="submit" name="btn_submit" value="我是submit" id="btn_submit" />
 
    <input type="button" name="btn" value="我是真Button" onclick="javascript:__doPostBack(&#39;btn&#39;,&#39;&#39;)" id="btn" />

在設計畫面就加上onkeypress

  <!--UseSubmitBehavior預設"true"-->
    <asp:Button runat="server" ID="btn_submit"  Text="我是submit"  onkeypress=""
         onclick="btn_submit_Click" />
 
    <asp:Button runat="server" ID="btn"  Text="我是真Button" UseSubmitBehavior="false"  onkeypress=""
         onclick="btn_Click" />


    <!--onkeypress不給值,才能真正用鍵盤觸發Server端事件-->

呈現的HTML

   <!--UseSubmitBehavior預設"true"-->
    <input type="submit" name="btn_submit" value="我是submit" id="btn_submit" onkeypress="" />
 
    <input type="button" name="btn" value="我是真Button" onclick="javascript:__doPostBack(&#39;btn&#39;,&#39;&#39;)" id="btn" onkeypress="" />

 

結論:最好加上onkeypress(不給值)安心過A+檢測。

 

13. ImageButton

通常會搭配做滑鼠移過置換圖片效果,請參考以下寫法

ASP.net伺服器標記

<asp:ImageButton ID="ImageButton1" runat="server" 
             ImageUrl="images/Source.jpg" 
             onmouseout='this.src="images/Source.jpg"'
             onblur='this.src="images/Source.jpg"' 
             onmouseover='this.src="images/MouseOver.jpg"'
             onfocus='this.src="images/MouseOver.jpg"' 
             AlternateText="必填alt" 
             OnClick="ImageButton1_Click"
             onkeypress="ImageButton1_Click" />

呈現的HTML

<input type="image" name="ImageButton1" id="ImageButton1" onmouseout="this.src=&quot;images/Source.jpg&quot;" onblur="this.src=&quot;images/Source.jpg&quot;" onmouseover="this.src=&quot;images/MouseOver.jpg&quot;" onfocus="this.src=&quot;images/MouseOver.jpg&quot;" onkeypress="ImageButton1_Click" src="images/Source.jpg" alt="必填alt" style="border-width:0px;" />

結論:要加AlternateText和onkeypress就可以過A+。

2011.9.30 追加發現:即使沒有加BorderWidth屬性,呈現出的Html會加style="border-width:0px;"

 

14 LinkButton

ASP.net伺服器標記

<asp:LinkButton ID="LinkButton1" Text="A" runat="server" onclick="LinkButton1_Click"  />

呈現的HTML

<a id="LinkButton1" href="javascript:__doPostBack(&#39;LinkButton1&#39;,&#39;&#39;)">A</a>

結論:因為是href=”javascript:__doPostBack();”,所以確定不用加onkeypress就可以過A+。

題外話,若這樣寫的話

<asp:LinkButton ID="LinkButton" Text="A" runat="server" onclick="LinkButton_Click" >
  <img border="0" src="images/Source.jpg" alt="必填" />
</asp:LinkButton>

呈現的HTML

<a id="LinkButton" href="javascript:__doPostBack(&#39;LinkButton&#39;,&#39;&#39;)">
    <img border="0" src="images/Source.jpg" alt="必填" />
</a>

操作起來感覺像ImageButton,實際上內容是超連結包圖片

 

15. FileUpload

ASP.net伺服器標記

<asp:FileUpload ID="FileUpload1"   runat="server"/> 

呈現的HTML

<input type="file" name="FileUpload1" id="FileUpload1" /> 

結論:沒什麼特別設定,可以過A+。

 

16. MultiView
17. View

ASP.net伺服器標記

<asp:MultiView ID="MultiView1" runat="server" onactiveviewchanged="MultiView1_ActiveViewChanged">
        <asp:View ID="View1" runat="server">
            A
        </asp:View>
        <asp:View ID="View2" runat="server">
            B
        </asp:View>
</asp:MultiView>

呈現的HTML:無

結論:MultiView和View都是空白的Container,因為無HTML Tag,當然也就可以通過A+。

 

18. Panel

ASP.net伺服器標記

<asp:Panel ID="Panel1" runat="server">
    A
</asp:Panel>

呈現的HTML

<div id="Panel1">
    A
</div>

結論:Panel是HTML <div>的Container,可以通過A+。

 

19. PlaceHolder

ASP.net伺服器標記

<asp:PlaceHolder ID="PlaceHolder1" runat="server">
       A
</asp:PlaceHolder>

呈現的HTML:無

說明:因為是沒有HTML Tag的Container,可以通過A+
為了避免破壞美工人員的版型,我自己也常使用PlaceHolder取代Panel,兩者在使用上大同小異。

 

20. Menu

ASP.net伺服器標記

<asp:Menu ID="Menu1" runat="server">
      <Items>
            <asp:MenuItem Text="A" Value="A"></asp:MenuItem>
            <asp:MenuItem Text="B" Value="B"></asp:MenuItem>
            <asp:MenuItem Text="C" Value="C"></asp:MenuItem>
      </Items>
</asp:Menu>

呈現的HTML,<a>會自動加onclick事件

<a href="#Menu1_SkipLink"><img alt="略過巡覽連結" src="/testAplus/WebResource.axd?d=ZyICRpmMjOQ_uiS7ICGIGYp-6b6UuePx1mwIUPlSBP_iZvPepn-QpGwoAXemYK27AzmqKkdmsJk9M-wHDAhqTRvu5V_SPOcsqjfGELKzMLA1&amp;t=634402701822635329" width="0" height="0" style="border-width:0px;" /></a>
<div id="Menu1">
    <ul class="level1">
        <li><a class="level1 selected" href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;A&#39;)">A</a></li>
                <li><a class="level1"          href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;B&#39;)">B</a></li>
                <li><a class="level1"          href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;C&#39;)">C</a></li>
    </ul>
</div><a id="Menu1_SkipLink"></a>

嘗試為<a>加onkeypress,MenuItem無法加Attributes

所以用Menu直接加Attributes["onkeypress"]試試看

呈現的HTML

<a href="#Menu1_SkipLink"><img alt="略過巡覽連結" src="/testAplus/WebResource.axd?d=ZyICRpmMjOQ_uiS7ICGIGYp-6b6UuePx1mwIUPlSBP_iZvPepn-QpGwoAXemYK27AzmqKkdmsJk9M-wHDAhqTRvu5V_SPOcsqjfGELKzMLA1&amp;t=634402701822635329" width="0" height="0" style="border-width:0px;" /></a>
<div onkeypress="Menu1_onkeypress();" id="Menu1">
    <ul class="level1">
        <li><a class="level1 selected" href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;A&#39;)">A</a></li>
                <li><a class="level1"          href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;B&#39;)">B</a></li>
                <li><a class="level1"          href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;C&#39;)">C</a></li>
    </ul>
</div><a id="Menu1_SkipLink"></a>

結果onkeypress並不是加在和onclick同一個Tag中,而是加在<div>

改用修改樣版的方式,只會變成

<li><a class="level1" href="#" onclick="__doPostBack(&#39;Menu1&#39;,&#39;A&#39;)">
           超連結包起來的文字
    </a>
</li>

結論:Menu無法通過A+,須改用jQuery UI的替代方案

38 jQuery And CSS Drop Down Multi Level Menu Solutions

10 Best jQuery Menu Plugins – AjaxLine

25 jQuery Drop Down Menu Scripts  Vandelay Design Blog

2012.9.14 追記:MSDN有人提出解法,override Page的Render,說不定TreeView也可以依樣畫蘆?

ASP.NET 的 Menu 控制項 無法在 Android 上運作(黃小榮)

 

21. TreeView

ASP.net伺服器標記

<asp:TreeView ID="TreeView1" runat="server" >
        <Nodes>
            <asp:TreeNode Text="A" Value="A" >
                <asp:TreeNode Text="A-1" Value="A-1"></asp:TreeNode>
            </asp:TreeNode>
        </Nodes>
</asp:TreeView>

呈現的HTML,A和A-1節點所在的超連結被自動加onclick事件

<a href="#TreeView1_SkipLink"><img alt="略過巡覽連結。" src="/testAplus/WebResource.axd?d=ZyICRpmMjOQ_uiS7ICGIGYp-6b6UuePx1mwIUPlSBP_iZvPepn-QpGwoAXemYK27AzmqKkdmsJk9M-wHDAhqTRvu5V_SPOcsqjfGELKzMLA1&amp;t=634402701822635329" width="0" height="0" style="border-width:0px;" /></a>
<div id="TreeView1">
    <table cellpadding="0" cellspacing="0" style="border-width:0;">
        <tr>
            <td><a id="TreeView1n0" href="javascript:TreeView_ToggleNode(TreeView1_Data,0,TreeView1n0,&#39; &#39;,TreeView1n0Nodes)"><img src="/testAplus/WebResource.axd?d=cMkl8rKLA1w_DOHuoXhUFRWuNhmJjN0XPq8umq0y2M0T8ZKcqiICXVG7lLeUAbDbSYGZEF5I8umpJx_5y_8NN5_jjYEVLY6AE3fQf724xo7ciZZdjnZwMfiB1w_TUibS0&amp;t=634402701822635329" alt="摺疊 A" style="border-width:0;" /></a></td>
                        <td style="white-space:nowrap;"><a class="TreeView1_0" href="javascript:__doPostBack(&#39;TreeView1&#39;,&#39;sA&#39;)" onclick="TreeView_SelectNode(TreeView1_Data, this,&#39;TreeView1t0&#39;);" id="TreeView1t0">A</a></td>
        </tr>
    </table><div id="TreeView1n0Nodes" style="display:block;">
    <table cellpadding="0" cellspacing="0" style="border-width:0;">
        <tr>
            <td><div style="width:20px;height:1px"></div></td>
                        <td><img src="/testAplus/WebResource.axd?d=IVsTWyp_B_x6D1UPog_gzdmCyT44_Dbztc8veURgOJ2T29n6-Wy4uyrCk8TkxxlZ69Vk5vR0anoELYQBWadwdaVWh4bWLtVEdm_tlCGWXQsKi4cIe1QqRTDiQNp2Pw7q0&amp;t=634402701822635329" alt="" /></td>
                        <td style="white-space:nowrap;"><a class="TreeView1_0" href="javascript:__doPostBack(&#39;TreeView1&#39;,&#39;sA\\A-1&#39;)" onclick="TreeView_SelectNode(TreeView1_Data, this,&#39;TreeView1t1&#39;);" id="TreeView1t1">A-1</a></td>
        </tr>
    </table>
    </div>
</div><a id="TreeView1_SkipLink"></a>

嘗試加入onkeypress

  
TreeNode無法加入Attributes,所以用TreeView直接加Attributes["onkeypress"]試試看

呈現的HTML

<a href="#TreeView1_SkipLink"><img alt="略過巡覽連結。" src="/testAplus/WebResource.axd?d=ZyICRpmMjOQ_uiS7ICGIGYp-6b6UuePx1mwIUPlSBP_iZvPepn-QpGwoAXemYK27AzmqKkdmsJk9M-wHDAhqTRvu5V_SPOcsqjfGELKzMLA1&amp;t=634402701822635329" width="0" height="0" style="border-width:0px;" /></a>
<div id="TreeView1" onkeypress="TreeView1_onkeypress();">
    <table cellpadding="0" cellspacing="0" style="border-width:0;">
        <tr>
            <td><a id="TreeView1n0" href="javascript:TreeView_ToggleNode(TreeView1_Data,0,TreeView1n0,&#39; &#39;,TreeView1n0Nodes)"><img src="/testAplus/WebResource.axd?d=cMkl8rKLA1w_DOHuoXhUFRWuNhmJjN0XPq8umq0y2M0T8ZKcqiICXVG7lLeUAbDbSYGZEF5I8umpJx_5y_8NN5_jjYEVLY6AE3fQf724xo7ciZZdjnZwMfiB1w_TUibS0&amp;t=634402701822635329" alt="摺疊 A" style="border-width:0;" /></a></td>
                        <td style="white-space:nowrap;"><a class="TreeView1_0" href="javascript:__doPostBack(&#39;TreeView1&#39;,&#39;sA&#39;)" onclick="TreeView_SelectNode(TreeView1_Data, this,&#39;TreeView1t0&#39;);" id="TreeView1t0">A</a></td>
        </tr>
    </table><div id="TreeView1n0Nodes" style="display:block;">
        <table cellpadding="0" cellspacing="0" style="border-width:0;">
        <tr>
            <td><div style="width:20px;height:1px"></div></td>
                        <td><img src="/testAplus/WebResource.axd?d=IVsTWyp_B_x6D1UPog_gzdmCyT44_Dbztc8veURgOJ2T29n6-Wy4uyrCk8TkxxlZ69Vk5vR0anoELYQBWadwdaVWh4bWLtVEdm_tlCGWXQsKi4cIe1QqRTDiQNp2Pw7q0&amp;t=634402701822635329" alt="" /></td>
                        <td style="white-space:nowrap;"><a class="TreeView1_0" href="javascript:__doPostBack(&#39;TreeView1&#39;,&#39;sA\\A-1&#39;)" onclick="TreeView_SelectNode(TreeView1_Data, this,&#39;TreeView1t1&#39;);" id="TreeView1t1">A-1</a></td>
        </tr>
        </table>
    </div>
</div><a id="TreeView1_SkipLink"></a>

結果onkeypress加在<div>並不是加在和onclick同一個<a>中

結論:TreeView無法通過A+,須改用jQuery UI的替代方案 ,例如:jQuery TreeView

 

22. Chart

ASP.net伺服器標記

<asp:SqlDataSource runat="server" id="sds_test" 
        ConnectionString="<%$ ConnectionStrings:NorthwindChineseConnectionString %>"
         SelectCommand="Select CategoryID,count(*) as 筆數
                        From Products
                        Group by CategoryID"/>    

    /*******************************************************************/
    <asp:Chart ID="Chart1" runat="server" DataSourceID="sds_test" 
        AlternateText="alt必填">
        <Series>
            <asp:Series Name="Series1" XValueMember="CategoryID" YValueMembers="筆數" >
            </asp:Series>
        </Series>
        <ChartAreas>
            <asp:ChartArea Name="ChartArea1">
            </asp:ChartArea>
        </ChartAreas>
    </asp:Chart> 

呈現的HTML

分三種RenderType

使用預設的ImageTag

<img id="Chart1" src="/testAplus/ChartImg.axd?i=chart_964cd50b67a1455a94fb49e9fe580d12_1.png&amp;g=60e0a262db354e63a63594591355fb4f" alt="alt必填" style="height:300px;width:300px;border-width:0px;" /> 

結論:RenderType使用預設的ImageTag,Chart須加AlternateText

若RenderType使用ImageMap的HTML情況

<img id="Chart1" src="ChartPic_#SEQ(300,3)?4f1ca5fd-818e-4380-97e7-cbe339819138" alt="alt必填" usemap="#Chart1ImageMap" style="height:300px;width:300px;border-width:0px;" />
<map name="Chart1ImageMap" id="Chart1ImageMap">
    <area shape="rect" coords="0,0,0,0" alt="" />
</map>

<map>裡面的<area alt="" />無疑是給自己找麻煩

 

23. Calendar

ASP.net伺服器標記

<asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>

呈現的HTML

   <table id="Calendar1" cellspacing="0" cellpadding="2" title="Calendar" border="0" style="border-width:1px;border-style:solid;border-collapse:collapse;">
	<tr><td colspan="7" style="background-color:Silver;"><table cellspacing="0" border="0" style="width:100%;border-collapse:collapse;">
		<tr><td style="width:15%;"><a href="javascript:__doPostBack('Calendar1','V4108')" style="color:Black" title="Go to the previous month">&lt;</a></td><td align="center" style="width:70%;">2011年5月</td><td align="right" style="width:15%;"><a href="javascript:__doPostBack('Calendar1','V4169')" style="color:Black" title="Go to the next month">&gt;</a></td></tr>
	</table></td></tr><tr><th align="center" abbr="星期日" scope="col">週日</th><th align="center" abbr="星期一" scope="col">週一</th><th align="center" abbr="星期二" scope="col">週二</th><th align="center" abbr="星期三" scope="col">週三</th><th align="center" abbr="星期四" scope="col">週四</th><th align="center" abbr="星期五" scope="col">週五</th><th align="center" abbr="星期六" scope="col">週六</th></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4131')" style="color:Black" title="4月24日">24</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4132')" style="color:Black" title="4月25日">25</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4133')" style="color:Black" title="4月26日">26</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4134')" style="color:Black" title="4月27日">27</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4135')" style="color:Black" title="4月28日">28</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4136')" style="color:Black" title="4月29日">29</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4137')" style="color:Black" title="4月30日">30</a></td></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4138')" style="color:Black" title="5月1日">1</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4139')" style="color:Black" title="5月2日">2</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4140')" style="color:Black" title="5月3日">3</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4141')" style="color:Black" title="5月4日">4</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4142')" style="color:Black" title="5月5日">5</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4143')" style="color:Black" title="5月6日">6</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4144')" style="color:Black" title="5月7日">7</a></td></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4145')" style="color:Black" title="5月8日">8</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4146')" style="color:Black" title="5月9日">9</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4147')" style="color:Black" title="5月10日">10</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4148')" style="color:Black" title="5月11日">11</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4149')" style="color:Black" title="5月12日">12</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4150')" style="color:Black" title="5月13日">13</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4151')" style="color:Black" title="5月14日">14</a></td></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4152')" style="color:Black" title="5月15日">15</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4153')" style="color:Black" title="5月16日">16</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4154')" style="color:Black" title="5月17日">17</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4155')" style="color:Black" title="5月18日">18</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4156')" style="color:Black" title="5月19日">19</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4157')" style="color:Black" title="5月20日">20</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4158')" style="color:Black" title="5月21日">21</a></td></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4159')" style="color:Black" title="5月22日">22</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4160')" style="color:Black" title="5月23日">23</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4161')" style="color:Black" title="5月24日">24</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4162')" style="color:Black" title="5月25日">25</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4163')" style="color:Black" title="5月26日">26</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4164')" style="color:Black" title="5月27日">27</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4165')" style="color:Black" title="5月28日">28</a></td></tr><tr><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4166')" style="color:Black" title="5月29日">29</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4167')" style="color:Black" title="5月30日">30</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4168')" style="color:Black" title="5月31日">31</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4169')" style="color:Black" title="6月1日">1</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4170')" style="color:Black" title="6月2日">2</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4171')" style="color:Black" title="6月3日">3</a></td><td align="center" style="width:14%;"><a href="javascript:__doPostBack('Calendar1','4172')" style="color:Black" title="6月4日">4</a></td></tr>
</table>

結論:因為可以按的部份都是href=”javascript:__doPostBack();”,所以不用加onkeypress就可以過A+。

 

24. ImageMap

說明:

請美工人員用Dreamweaver切<map > <area alt="alt必填"></map>來替代此控制項。

 

 

 

25. GridView

ASP.net伺服器標記(加入排序和分頁)

 <asp:SqlDataSource runat="server" ID="sds_test" 
        ConnectionString="<%$ ConnectionStrings:NorthwindChineseConnectionString %>" 
        SelectCommand="SELECT [ProductID], [ProductName] FROM [Products]" /> 
/**********************************************************************/
    <asp:GridView ID="GridView1" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="ProductID" 
        DataSourceID="sds_test">
        <Columns>
            <asp:BoundField DataField="ProductID" HeaderText="ProductID" 
                InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
            <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
                SortExpression="ProductName" />
        </Columns>
    </asp:GridView> 

呈現的HTML

<table cellspacing="0" rules="all" border="1" id="GridView1" style="border-collapse:collapse;">
        <tr>
            <th scope="col"><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Sort$ProductID&#39;)">ProductID</a></th><th scope="col"><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Sort$ProductName&#39;)">ProductName</a></th>
        </tr><tr>
            <td>1</td><td>蘋果汁</td>
        </tr><tr>
            <td>2</td><td>牛奶</td>
        </tr><tr>
            <td>3</td><td>蕃茄醬</td>
        </tr><tr>
            <td>4</td><td>鹽巴</td>
        </tr><tr>
            <td>5</td><td>麻油</td>
        </tr><tr>
            <td>6</td><td>醬油</td>
        </tr><tr>
            <td>7</td><td>海鮮粉</td>
        </tr><tr>
            <td>8</td><td>胡椒粉</td>
        </tr><tr>
            <td>9</td><td>讚油雞</td>
        </tr><tr>
            <td>10</td><td>大甲蟹</td>
        </tr><tr>
            <td colspan="2"><table>
                <tr>
                    <td><span>1</span></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$2&#39;)">2</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$3&#39;)">3</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$4&#39;)">4</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$5&#39;)">5</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$6&#39;)">6</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$7&#39;)">7</a></td><td><a href="javascript:__doPostBack(&#39;GridView1&#39;,&#39;Page$8&#39;)">8</a></td>
                </tr>
            </table></td>
        </tr>
    </table>

結論:排序和分頁,可以按的部份都是href=”javascript:__doPostBack();”,所以不用加onkeypress就可以過A+。

2011.11.26 追記

<table>外面其實還有一個<div>來包住此<table>...</table>

 

26. ListView

ASP.net伺服器標記(加入分頁功能)

 

<asp:SqlDataSource runat="server" ID="sds_test" ConnectionString="<%$ ConnectionStrings:NorthwindChineseConnectionString %>"
        SelectCommand="SELECT [ProductID], [ProductName] FROM [Products]" /> 
/***********************************************************************************************************/
    <asp:ListView ID="ListView1" runat="server" DataKeyNames="ProductID" DataSourceID="sds_test">
        <ItemTemplate>
            <tr style="">
                <td>
                    <asp:Label ID="ProductIDLabel" runat="server" Text='<%# Eval("ProductID") %>' />
                </td>
                <td>
                    <asp:Label ID="ProductNameLabel" runat="server" Text='<%# Eval("ProductName") %>' />
                </td>
            </tr>
        </ItemTemplate>
        <LayoutTemplate>
            <table id="itemPlaceholderContainer" runat="server" border="0" style="">
                <tr runat="server" style="">
                    <th runat="server">
                        ProductID
                    </th>
                    <th runat="server">
                        ProductName
                    </th>
                </tr>
                <tr id="itemPlaceholder" runat="server">
                </tr>
                <tr>
                    <td>
                        <asp:DataPager ID="DataPager1" runat="server">
                            <Fields>
                                <asp:NextPreviousPagerField ButtonType="Link" ShowFirstPageButton="True" ShowNextPageButton="False"
                                    ShowPreviousPageButton="False" />
                                <asp:NumericPagerField />
                                <asp:NextPreviousPagerField ButtonType="Link" ShowLastPageButton="True" ShowNextPageButton="False"
                                    ShowPreviousPageButton="False" />
                            </Fields>
                        </asp:DataPager>
                    </td>
                </tr>
            </table>
        </LayoutTemplate>
    </asp:ListView>

 

主要注意DataPager的PagerField,ButtonType有三種:Button、Link、Image

Button呈現的HTML

<span id="ListView1_DataPager1">
<input type="submit" name="ListView1$DataPager1$ctl00$ctl00" value="First" disabled="disabled" />&nbsp;
<span>1</span>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl01&#39;,&#39;&#39;)">2</a>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl02&#39;,&#39;&#39;)">3</a>&nbsp;
<input type="submit" name="ListView1$DataPager1$ctl02$ctl00" value="Last" />&nbsp;
</span>

<input>沒有被加onclick,所以無需加onkeypress

Link呈現的HTML

<span id="ListView1_DataPager1">
<a class="aspNetDisabled">第一頁</a>&nbsp;
<span>1</span>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl01&#39;,&#39;&#39;)">2</a>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl02&#39;,&#39;&#39;)">3</a>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl02$ctl00&#39;,&#39;&#39;)">最後一頁</a>&nbsp;
</span> 

Image呈現的HTML(<input>會被自動加alt說明文字)

<span id="ListView1_DataPager1">
<input type="image" name="ListView1$DataPager1$ctl00$ctl00" disabled="disabled" src="images/Source.jpg" alt="First" style="border-width:0px;" />&nbsp;
<span>1</span>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl01&#39;,&#39;&#39;)">2</a>&nbsp;
<a href="javascript:__doPostBack(&#39;ListView1$DataPager1$ctl01$ctl02&#39;,&#39;&#39;)">3</a>&nbsp;
<input type="image" name="ListView1$DataPager1$ctl02$ctl00" src="images/Source.jpg" alt="Last" style="border-width:0px;" />&nbsp;
</span>

說明:DataPager的三種ButtonType,經過機器檢測都可以通過A+,不過畢竟Button和Image呈現出來的是input,難保不會有狀況

這時須改用Link的ButtonType或手寫自訂分頁

 

27. Silverlight、Flash、Media Player的<object>、<iframe>

拿Silverlight當範例,</object>前面要有說明文字,<iframe>屬性要加title

<div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
		  <param name="source" value="ClientBin/testSilverlightObject.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="4.0.50826.0" />
		  <param name="autoUpgrade" value="true" />
		  <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 			  <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
		  </a>
        這是Silverlight應用程式
	    </object>
        <iframe title="iframe要加title" id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>
    </div>

2011.5.31 追記,</object>前面的說明文字在Firefox上瀏覽的話會直接顯示該說明文字,所以改成以下寫法也可以過無障礙

這是Silverlight應用程式 ↓
<span style="display:none;">這是Silverlight應用程式</span>


28. UpdatePanel

<!--ScriptManager位置-->
    <asp:ScriptManager runat="server" />
    <!--Timer位置-->
    <asp:Timer ID="Timer1" runat="server" Interval="1000" />
    <!--UpdatePanel位置-->
    <asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional">
        <ContentTemplate>
            <!--Literal位置-->
            <asp:Literal id="li_Text" runat="server" />
        </ContentTemplate>
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
        </Triggers>
    </asp:UpdatePanel>

呈現結果

 <!--Timer位置-->
    <span id="Timer1" style="visibility:hidden;display:none;"></span>
    <!--UpdatePanel位置-->
    <div id="UpdatePanel1">
            <!--Literal位置-->
    </div>
 

結論:UpdatePanel呈現出來的只是<div>,可以通過A+

 

29. 驗證控制項

<form id="form1" runat="server">

    <asp:TextBox runat="server" ID="txt_TextBox" />
    <!--RequiredFieldValidator1,Display設成None的話,呈現出Html style為display:none;驗證不通過也不顯示-->
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1"   
        ErrorMessage="TextBox必填" ControlToValidate="txt_TextBox"
        runat="server" Display="None"   />  
        <!--RequiredFieldValidator2 Display預設Static-->
         <asp:RequiredFieldValidator ID="RequiredFieldValidator2"    Display="Static"
        ErrorMessage="TextBox必填" ControlToValidate="txt_TextBox"
        runat="server" />  
        <!--RequiredFieldValidator3 Display設成Dynamic的話,呈現出Html style為display:none;-->
         <asp:RequiredFieldValidator ID="RequiredFieldValidator3"   
        ErrorMessage="TextBox必填" ControlToValidate="txt_TextBox"
        runat="server" Display="Dynamic" />  
    <asp:Button Text="提交" ID="btn_submit" runat="server" />
    </form>

執行呈現結果Html

image

驗證控制項呈現出來的都是span,可以過A+

但要注意Display屬性設成Static(visibility:hidden)和Dynamic(display:none)的差別

 

  <asp:ValidationSummary ID="ValidationSummary1"  runat="server"   />

ValidationSummary控制項呈現出的Html

 <div id="ValidationSummary1" style="color:Red;display:none;">

ValidationSummary呈現出div,可以過A+

 

30. 其他

通常jQuery UI Plugin一定過得了A+,因為那些滑鼠事件都寫在Javascript裡,HTML部份機器是掃不出來

所以若有遇到過不了無障礙的控制項,或不曉得該控制項如何加鍵盤事件的話,可以考慮使用jQuery UI Plugin

 

 

 

 

最後提供一個通過AA無障礙網頁標準的技巧

AA無障礙網頁最令人頭痛的是任何Tag的大小都不能用絕對像素,必須用百分比來顯示

例如:<table width=”100%”>

               <tr><td></td></tr>

            </table>

這對美工人員來說,把圖片拆成HTML方面可能會有困難

但只要把那些定位、大小的屬性全寫在CSS

HTML都用id、class來套CSS樣式的話,AA無障礙標準就會好過一點。

 

 

 

 

 

以上如有錯誤,請不吝指教,歡迎提出。

轉載文章是可以,但一定要貼上來源超連結,因為此文章會一直更新,我不想讓有需要的人被誤導

下一篇:

[ASP.net WebForm] 撰寫無障礙網頁的技巧&分享 - Part2 人工檢測篇