AJAX 滑块控件和 GridView 滚子






4.86/5 (31投票s)
创建一个罗洛迪斯类型的控件,使用 SliderExtender 控件和 GridView 来查看联系人。
 
 
引言
借鉴大多数移动设备(尤其是 iPhone)的思路,使用滑动罗洛迪斯的方式访问列表中的人员是一种非常方便快捷的导航方式。该项目结合使用了 SliderExtender、GridView、一些 CSS 技巧和 UpdatePanel。
背景
我希望我的网页像我的手机一样方便。
第一步:基本的滑块扩展器设置
首先,我们做一些简单的事情。在支持 AJAX 的 ASPX 页面上放置一个滑块和一个文本框。这没什么意思。但请注意,我已经为 SliderExtender 设置了 Maximum 为 26,Minimum 为 0。如果您运行此页面,您将看到一个垂直滑块,仅此而已。
<asp:TextBox runat="server" ID="SliderBox" />
  <cc1:SliderExtender runat="server" ID="SliderBoxExtender" 
     Maximum="26" Minimum="0" TargetControlID="SliderBox" /> 
它应该如下所示
 
 
第二步:垂直格式化
默认情况下,滑块是从左到右的。当然,这也可以正常工作,但我希望滑块是垂直的。因此,使用一些样式,我设计了这种布局。根据您的样式表中的其他属性,控件的高度和长度可能需要调整。坦率地说,我只是调整了滑块的 Length 属性,直到它与我的字母列的高度匹配。请注意,我的段落标签的 font-size 属性是以 px 为单位的。这一点**非常重要**。使用 px 进行字体样式设置可以确保用户无法调整它们的大小(从而破坏我们滑块控件的精确高度设置!)。我在这里还有很多其他样式规则,它们将在稍后发挥作用。
<style>        
        body{font-family: "trebuchet ms", sans-serif;
            font-size: 10pt;
            background-color: #fff;
            color: #555;
	        line-height: 1.7em;}
	    p {paddding-top:0px;}
        table {border:none; border-collapse:collapse;margin-bottom: 1.5em;}
        table td{vertical-align:top;position:relative;}
        td p {padding:4px;margin:-1px 0px;font-size:8px;width:12px;line-height:10px;
              border: solid 1px #d1d1d1;cursor:hand;}
        td p.letterSelected{font-weight:bold; width:14px;
                            background-color:#c1c1c1;font-size:10px;color:#fff;
                            padding:4px 4px 4px 6px; border:solid 1px #d1d1d1;}
        .letterbox{
        position:absolute;top:100px; left:100px; height:60px; width:100px; z-index:5;
        border: solid 1px gray;background:#fff; filter:alpha(opacity=70); opacity:.7; 
        text-align:center; font-size:48px;padding-top:30px; 
        font-weight:bold;display:none;
        }
        
        .rowA{background:#c1c1c1;}
        .rowB{background:#f1f1f1;}
</style>
<table>
    <td>
        <asp:TextBox runat="server" ID="SliderBox" />
        <cc1:SliderExtender runat="server" 
            ID="SliderBoxExtender" Maximum="26" Length="425"
            Minimum="0" TargetControlID="SliderBox" Orientation="vertical" />    
    </td>
    <td>
        <p id="row_0">All</p>
        <p id="row_1">A</p>
        <p id="row_2">B</p>
        <p id="row_3">C</p>
        <p id="row_4">D</p>
        <p id="row_5">E</p>
        <p id="row_6">F</p>
        <p id="row_7">G</p>
        <p id="row_8">H</p>
        <p id="row_9">I</p>
        <p id="row_10">J</p>
        <p id="row_11">K</p>
        <p id="row_12">L</p>
        <p id="row_13">M</p>
        <p id="row_14">N</p>
        <p id="row_15">O</p>
        <p id="row_16">P</p>
        <p id="row_17">Q</p>
        <p id="row_18">R</p>
        <p id="row_19">S</p>
        <p id="row_20">T</p>
        <p id="row_21">U</p>
        <p id="row_22">V</p>
        <p id="row_23">W</p>
        <p id="row_24">X</p>
        <p id="row_25">Y</p>
        <p id="row_26">Z</p>
    </td>
</table>
这是它的样子
 
 
第三步:将数字转换为字母
不幸的是,滑块扩展器只能在数字范围内滑动。当然,我们希望用户能够滑动字母。那么问题来了:如何将数字转换为字母?我猜有很多方法可以做到。在我的示例中,我使用了带有编号 ID 的段落容器。然后我使用 JavaScript 来确定哪个被选中,并使用 innerHTML 属性来提取匹配的字母。听起来很复杂?其实不然。
首先,我们需要拦截所有滑块扩展器的操作。这意味着要将我们自己的函数附加到控件的事件上。这出奇地简单。在不深入每个函数的情况下,这里是如何将函数附加到 Ajax 控件的事件上的。
 //! set the Java functions to each of the slider events
 function pageLoad(sender, e) {
 var slider = $find('<%=SliderBoxExtender.ClientID %>');
 slider.add_slideStart(sliderStart);
 slider.add_slideEnd(sliderEnd);
 slider.add_valueChanged(valChanged);
 }
我使用了 SliderBoxExtender.ClientID 语法来获取 .NET 在渲染时生成的 ControlID。
现在我们可以开始编写在这些事件中发生的事情了。这就是显示选定字母和突出显示选定 <p> 标签的魔法发生的地方。
- sliderStart:当用户首次在滑块句柄上按下鼠标时触发的函数。我们需要打开字母框(一个将悬停在我们的- GridView上方的单个字母框)。
 - function sliderStart() { var fd = document.getElementById('LetterBox'); fd.style.display='inline'; }
- sliderEnd/- submitForm:当用户释放鼠标按钮时触发的函数。我们需要隐藏字母框并提交表单。但是,我们将- GridView放在- UpdatePanel中,因此我们不会提交表单,而是单击一个隐藏的按钮,该按钮作为异步触发器连接到我们的- UpdatePanel(参见- submitForm()函数)。我将提交表单的逻辑分开了,因为正如您将看到的,我希望能够单击字母以及滑动到它们,并获得相同的结果——网格的发布回更新。- function sliderEnd() { var fd = document.getElementById('LetterBox'); fd.style.display='none'; submitForm(); } function submitForm() { var hidBtn = document.getElementById('<%=hiddenButton.ClientID %>'); hidBtn.click(); }
- valChanged:真正起作用的函数,它完成了所有炫酷的功能。此函数更改字母框中的文本,并更改“活动”字母的- <p>标签的格式。- function valChanged() { //get the box that will display the letter chosen var fd = document.getElementById('LetterBox'); //get the box containing the value chosen by the Extender var valBox = document.getElementById('<%=SliderBox.ClientID %>'); //get the value of the extender var val = valBox.value; //set up a loop variable var i = 0 //create a row variable var grow //loop through numbers 0 through 26 for(i=0;i<27;i++) { //set our local row variable to the ID of one of our paragraph tags grow = document.getElementById('row_' + i); //if our paragraph ID matches the selected number if(i==val) //set the paragraph style to selected {grow.className = 'letterSelected'; //change the text of our Letter Box to the innerHTML //of our paragraph tag fd.innerHTML = grow.innerHTML; } //otherwise, set the style of our paragraph tag to nothing else{grow.className = '';} } }
现在是时候停下来看看我们目前的进展了。如果我们在 sliderEnd 函数中注释掉 JavaScript 的 submitForm() 部分,一切都应该按预期工作。
 
 
第四步:添加 UpdatePanel、GridView 和数据
我非常喜欢使用 ObjectDataSources,因此在本示例中我使用了它。这对您来说可能意义不大。但是,此 ODS 使用一个存储过程,该存储过程使用如下所示的 SQL 语法搜索我的 People 列表。
CREATE PROCEDURE dbo.usp_GetEmployeeList_FirstLetter 
	(@FirstLetter nvarchar(2))
AS
	SET NOCOUNT ON
		SELECT
			(E.LastName + ', ' + E.FirstName) as FullName,
			E.EmployeeID
		FROM
			TrainingWeb_Employee as E 
		WHERE
			E.LastName like @FirstLetter + '%'
			and E.[State] = 'Active'
		ORDER BY E.LastName, E.FirstName
	RETURN
因此,在 *.aspx 页面上,添加 UpdatePanel、ObjectDataSource、ObjectDataSource 的 SelectParameter 和 GridView。将 Gridview 连接到数据源。请注意,我还包含了一个隐藏按钮(在下面的代码底部),用于触发异步回发。这是从 submitForm() JavaScript 函数“单击”的按钮。
<asp:UpdatePanel runat="server" ID="PersonGridUpdatePanel" UpdateMode="conditional">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="hiddenButton" EventName="Click" />
    </Triggers>
    
    <ContentTemplate>
        <asp:ObjectDataSource runat="server" ID="PersonListData" 
		TypeName="myProject.Employee"
         SelectMethod="GetEmployeeList_FirstLetter">
            <SelectParameters>
                <asp:Parameter Name="FirstLetter" 
		DefaultValue="" ConvertEmptyStringToNull="false" />
            </SelectParameters> 
        </asp:ObjectDataSource>
        <asp:GridView ID="PersonGrid" Visible=false 
		runat="server" DataSourceID="PersonListData" AllowPaging="true"
        PageSize="20" AutoGenerateColumns="false" style="z-index:4;"
        RowStyle-CssClass="rowA" AlternatingRowStyle-CssClass="rowB">
            <Columns>
                <asp:BoundField DataField="Fullname" HeaderText="Person's Name" />
            </Columns>
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>
<asp:Button runat="server" ID="hiddenButton" style="display:none;" 
	OnClick="LetterSelected" UseSubmitBehavior="false" />
而且,我们需要在 aspx.vb 文件中添加几行来处理回发。具体来说,我们希望将 ObjectDataSource 的 Select 参数的值设置为已选择的字母。为了方便起见,我枚举了每个字母的选择,但使用这种方法,您可以通过使用 ASCII 编码而不是我简单的 1 到 26 的方法来国际化这些控件。
Protected Sub LetterSelected(ByVal sender As Object, ByVal e As EventArgs)
    Dim choice As LetterChoice = CType(SliderBox.Text, LetterChoice)
     If choice = LetterChoice.All Then
        PersonListData.SelectParameters("FirstLetter").DefaultValue = ""
    Else
        PersonListData.SelectParameters("FirstLetter").DefaultValue = choice.ToString()
    End If
 End Sub 
  Public Enum LetterChoice
    All = 0
    A = 1
    B = 2
    C = 3
    D = 4
    E = 5
    F = 6
    G = 7
    H = 8
    I = 9
    J = 10
    K = 11
    L = 12
    M = 13
    N = 14
    O = 15
    P = 16
    Q = 17
    R = 18
    S = 19
    T = 20
    U = 21
    V = 22
    W = 23
    X = 24
    Y = 25
    Z = 26
End Enum
说真的,就这些了。如果您确保 submitForm() 没有被注释掉(;)),您可以运行该页面,它将按预期工作。当然,在这样做了几次之后,我意识到作为用户,我期望能够单击字母以及使用滑块。没问题!只需向 <p> 标签添加一些 JavaScript 和一个小函数来更改滑块的值,我们就拥有了完整的功能。
新的 <p> 标签看起来像这样。
<td>
    <p id="row_0" onclick="setVal(this.id)">All</p>
    <p id="row_1" onclick="setVal(this.id)">A</p>
    <p id="row_2" onclick="setVal(this.id)">B</p>
    <p id="row_3" onclick="setVal(this.id)">C</p>
    <p id="row_4" onclick="setVal(this.id)">D</p>
    <p id="row_5" onclick="setVal(this.id)">E</p>
    <p id="row_6" onclick="setVal(this.id)">F</p>
    <p id="row_7" onclick="setVal(this.id)">G</p>
    <p id="row_8" onclick="setVal(this.id)">H</p>
    <p id="row_9" onclick="setVal(this.id)">I</p>
    <p id="row_10" onclick="setVal(this.id)">J</p>
    <p id="row_11" onclick="setVal(this.id)">K</p>
    <p id="row_12" onclick="setVal(this.id)">L</p>
    <p id="row_13" onclick="setVal(this.id)">M</p>
    <p id="row_14" onclick="setVal(this.id)">N</p>
    <p id="row_15" onclick="setVal(this.id)">O</p>
    <p id="row_16" onclick="setVal(this.id)">P</p>
    <p id="row_17" onclick="setVal(this.id)">Q</p>
    <p id="row_18" onclick="setVal(this.id)">R</p>
    <p id="row_19" onclick="setVal(this.id)">S</p>
    <p id="row_20" onclick="setVal(this.id)">T</p>
    <p id="row_21" onclick="setVal(this.id)">U</p>
    <p id="row_22" onclick="setVal(this.id)">V</p>
    <p id="row_23" onclick="setVal(this.id)">W</p>
    <p id="row_24" onclick="setVal(this.id)">X</p>
    <p id="row_25" onclick="setVal(this.id)">Y</p>
    <p id="row_26" onclick="setVal(this.id)">Z</p>
</td>
setVal 函数看起来像这样。
function setVal(pID)
{
    //grab the slider object
    var slider = $find('<%=SliderBoxExtender.ClientID %>');
     //remove the row_ text from the ID to get the "number" of the row
    var val = pID.replace('row_','')
     //set the value of the slider
    slider.set_Value(val);
     //run the valChanged() function to set all the controls appropriately
    valChanged();
     //trigger the postback
    submitForm();
} 
这是最终产品。
 
 
结论
设计需要零培训的网络控件是我的热情所在。这个罗洛迪斯控件对于人类体验来说非常常见,任何用户都应该能够弄清楚如何使用它。
历史
- 2009 年 5 月 5 日:初始发布


