控件绑定

1Repeater

复杂数据绑定控件

除了显示Text、Value这样简单的列表数据绑定控件之外,还有更复杂的数据绑定控件的要求,比如要将人员信息显示在界面上,包含姓名、年龄、照片等。这个时候就要使用Repeater、ListView等控件。

学HTML的时候是手写表格,但是项目中很多数据不是固定的,而是动态的。可以用Dom动态增加表格行,但是数据仍然是固定的,我们需要从数据库等地方取得动态的数据来显示。比如网站的友情链接列表就不是固定的,而是从数据库中动态读取动态生成的。

Repeater

Repeater(foreach)用于对绑定数据源中的数据进行遍历显示,每条数据以什么格式显示是由Repeater的<ItemTemplate>来决定的,模板会多次显示<ItemTemplate> </ItemTemplate>里的内容。

<%#eval_r(“Name”)%>表示在这个位置显示当前行的Name属性,注意调用Eval、Bind这些数据绑定方法的时候要用#。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<ItemTemplate>name(age):<%#eval_r("Name") %>(<%#eval_r("Age") %>)<hr/></ItemTemplate>

</asp:Repeater>

因为Eval就是将属性显示到指定的位置,因此也可以显示到文本框中<ItemTemplate>姓名:<input type=”text” value=’<%#eval_r(“Name”)%>’/></ItemTemplate>

注意不要写成value=” <%#eval_r(‘Name’)%>”,因为<%...%>中执行的是C#代码,’是字符,而不是字符串。

还可以用在服务器控件中

</div>

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<ItemTemplate><input type="text" value=‘<%#eval_r("Name") %>‘/>&nbsp;&nbsp;

<asp:TextBox runat="server" Text=‘<%#eval_r("Age") %>‘></asp:TextBox><hr/></ItemTemplate>

</asp:Repeater>

Repeater其他模板

1、<AlternatingItemTemplate >,设置隔行的不同显示风格,如果设定<AlternatingItemTemplate >,则奇数行用<ItemTemplate>模板,偶数行用<AlternatingItemTemplate >模板。隔行显示不同风格,是为了防止数据太多看串行了。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<ItemTemplate>

name:<%#eval_r("Name") %>(<%#eval_r("Age") %>)

</ItemTemplate>

<AlternatingItemTemplate >

<div style="

name:<%#eval_r("Name") %>(<%#eval_r("Age") %>)

</div>

</AlternatingItemTemplate>

</asp:Repeater>

2、HeaderTemplate、FooterTemplate:头部、尾部的模板,分别显示在所有数据的前面和后面。可以使用头部和尾部的模板定义一个Table。

3、SeparatorTemplate:两项数据之间的分隔符,比如换行符。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<ItemTemplate>

name:<%#eval_r("Name") %>(<%#eval_r("Age") %>)

</ItemTemplate>

<AlternatingItemTemplate >

<div style="

name:<%#eval_r("Name") %>(<%#eval_r("Age") %>)

</div>

</AlternatingItemTemplate>

<HeaderTemplate><p>人员数据</p></HeaderTemplate>

<FooterTemplate><p>制表人:zyang</p></FooterTemplate>

<SeparatorTemplate><hr/></SeparatorTemplate>  //数据之间分割线

</asp:Repeater>

2Repeater案例和练习

案例:显示人员信息,姓名、年龄、照片。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<ItemTemplate>

<tr><td><%#eval_r("Name") %></td><td><%#eval_r("Age") %></td><td><img alt="照片" src=‘images/<%#eval_r("PicPath") %>‘ /></td></tr>

</ItemTemplate>

<HeaderTemplate><Table></HeaderTemplate>

<FooterTemplate></Table></FooterTemplate>

</asp:Repeater>

3Repeater练习点评1

案例:鼠标放到图片上,图片动态放大,其他还原。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<HeaderTemplate><table id="tableImgs"><tr></HeaderTemplate>

<ItemTemplate><td><img height="50" width="50" src=‘images/<%#eval_r("PicPath") %>‘ /></td></ItemTemplate>

<FooterTemplate></tr></table></FooterTemplate>

</asp:Repeater>

<script type="text/javascript">

$("#tableImgs img").mouseenter(function () {

$(this).animate({ "height": "200", "width": "200" });

$("#tableImgs img").not($(this)).animate({ "height": "50", "width": "50" });

});

</script>

易错:在服务端控件中不能写’~/images/<%eval_r(“PicPath”)%>’,可以在页面中增加FormatImgURL方法,参数为object类型。对于服务端控件,只能ImageUrl=’<%eval_r(“PicPath”)%>’,不能再加另外的字符串。否则会找不到地址。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1">

<HeaderTemplate><table id="tableImgs"><tr></HeaderTemplate>

<ItemTemplate><td>

<asp:Image runat="server" Height="50" Width="50" ImageUrl=‘<%#FormatImgURL(eval_r("PicPath")) %>‘ />

</td></ItemTemplate>

<FooterTemplate></tr></table></FooterTemplate>

</asp:Repeater>

protected string FormatImgURL(object url)

{

return ResolveClientUrl("~/母版页/images/"+url);

}

5 Repeater练习点评

对于数据绑定的数据库中的数据,如果存在网址,最好存入的是完整的数据(加前缀),加上http://,如:http://www.baidu.com。否则需要在定义超链接<a>的href赋值之前,给其进行字符串连接。而对于服务端控件,则不能直接连接赋值。

6 Repeater的ItemDataBound事件

ItemDataBound

Repeater对于每行数据显示的时候都会调用ItemDataBound事件,在这个事件中可以对当前行进行处理,事件对象主要成员:

1、e.Item.ItemType为当前行的类型,ListItemType.Item为ItemTemplate行,AlternatingItem为AlternatingItemTemplate行,还有Header、Footer等取值,均是ListItemType类型的。

2、e.Item.ItemIndex当前行的序号。

3、e.Item. DataItem当前行绑定的对象,如果绑定的是数据集DataSet,则返回的数据需要转换为DataRowView类型使用。

如果要在ItemDataBound事件中对ItemTemplate模板中的控件做处理,则必须使用runat=”server”的ASP.Net控件或者HTML控件,为控件设置Id,然后用e.Item.FindControl根据Id来取得控件,注意在ASP.Net的模板中不能直接通过控件的Id来操作控件,必须用e.Item.FindControl找到控件才能操作。

案例:使年龄大于20的文本框变红。

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"

onitemdatabound="Repeater1_ItemDataBound">

<ItemTemplate>

Name:<%#eval_r("Name") %>,<asp:TextBox ID="txtAge" runat="server" Text=‘<%#eval_r("Age") %>‘></asp:TextBox>

</ItemTemplate>

<SeparatorTemplate><br /></SeparatorTemplate>

</asp:Repeater>

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)

{

//此处必须判断ListItemType.Item和ListItemType.AlternatingItem两种情况,否则只执行偶数行,不执行奇数行。

if (e.Item.ItemType == ListItemType.Item||e.Item.ItemType==ListItemType.AlternatingItem)

{

DataRowView rowView = (DataRowView)e.Item.DataItem;

var personRow = (theme.DAL.DataSetUsers.T_UsersRow)rowView.Row;

if (personRow.Age > 20)

{

TextBox txtAge = (TextBox)e.Item.FindControl("txtAge");

txtAge.BackColor = Color.Red;

}

}

}

7Repeater的ItemCommand

可以在模板中放置Button控件(Button、LinkButton、ImageButton),模板中的按钮一般不写Onclick事件响应,而是响应Repeater的ItemDataBound事件。

为Button控件设定CommandName、CommandArgument属性,然后在ItemDataBound事件读取e的CommandName、CommandArgument属性就可以获得发生事件的命令和行参数了。如果对数据进行了操作,则需要Repeater1.DataBind()来重新绑定,从数据库中刷新最新的数据。

aspx:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"

onitemdatabound="Repeater1_ItemDataBound"

onitemcommand="Repeater1_ItemCommand">

<ItemTemplate>

name:<%#eval_r("Name") %>,<asp:TextBox runat="server" ID="txtAge" Text=‘<%#eval_r("Age") %>‘></asp:TextBox><asp:Button runat="server" Text="涨一岁"  CommandName="IncAge" CommandArgument=‘<%#eval_r("Id")%>‘ /><br />

//把每行数据的Id通过CommandArgument传入

</ItemTemplate>

</asp:Repeater>

cs:

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)

{

//只执行CommandName=”IncAge”的按钮

if (e.CommandName == "IncAge")

{

int id = Convert.ToInt32(e.CommandArgument);

T_personTableAdapter adapter=new T_personTableAdapter();

//在DataSet中添加SQL查询:”update T_person set Age=Age+1 where [email protected];”

adapter.IncAgeById(id);

//DataBind()是为了从重新绑定数据,从而实现数据从Repeater中刷新数据库中的值

Repeater1.DataBind();

}

}

8Repeater综合案例

练习:人员管理程序(Id、用户名、启用状态),增加【禁用】当前行按钮,点击【禁用】,点击的时候提示是否真的要禁用,如果确定要禁用则将“启用状态”字段设置为“禁用”。禁用字段显示为红色。字段变为禁用后,行显示【启用】按钮,点击【启用】按钮将“启用状态”字段设置为“启用”。

在DataSet中添加两个update语句:

update T_UsersStatus set Status = ‘禁用’ where [email protected];→DisabledUserById(@Id).

update T_UsersStatus set Status = ‘启用’ where [email protected];→EnabledUserById(@Id).

在aspx中添加一个css,disabledRow:

<style type="text/css">

.disabledRow{background-color:Red;}

</style>

aspx代码:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"

onitemdatabound="Repeater1_ItemDataBound"

onitemcommand="Repeater1_ItemCommand">

<HeaderTemplate><table><tr><td>用户名</td><td>状态</td><td>操作</td></tr></HeaderTemplate>

<FooterTemplate></table></FooterTemplate>

<ItemTemplate><tr  runat="server" id="trRow"><td><%#eval_r("UserName") %></td><td><%#eval_r("Status")%></td><td>

<asp:Button ID="btnEnabled" runat="server" Text="禁用" CommandName="Enabled" CommandArgument=‘<%#eval_r("Id") %>‘ OnClientClick=‘return confirm("真的要禁用吗?");‘/>

<asp:Button ID="btnDisabled" runat="server" Text="启用" CommandName="Disabled" CommandArgument=‘<%#eval_r("Id") %>‘ OnClientClick=‘return confirm("真的要启用吗?");‘/>

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

</asp:Repeater>

cs代码:

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)

{

if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)

{

DataRowView rowView = (DataRowView)e.Item.DataItem;

var userRow = (theme.practice.DAL.UsersStatus.T_UsersStatusRow)rowView.Row;

if (userRow.Status == "禁用")

{

HtmlTableRow trRow=(HtmlTableRow)e.Item.FindControl("trRow");

trRow.Attributes["class"] = "disabledRow";

Button btnEnabled = (Button)e.Item.FindControl("btnEnabled");

Button btnDisabled = (Button)e.Item.FindControl("btnDisabled");

btnEnabled.Visible = false;

btnDisabled.Visible = true;

}

else if (userRow.Status == "启用")

{

HtmlTableRow trRow = (HtmlTableRow)e.Item.FindControl("trRow");

//trRow.Attributes["class"] = "";

Button btnEnabled = (Button)e.Item.FindControl("btnEnabled");

Button btnDisabled = (Button)e.Item.FindControl("btnDisabled");

btnEnabled.Visible = true;

btnDisabled.Visible = false;

}

else

{

throw new Exception("非法Status字段");

}

}

}

protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)

{

if (e.CommandName == "Enabled")

{

int id = Convert.ToInt32(e.CommandArgument);

T_UsersStatusTableAdapter adapter = new T_UsersStatusTableAdapter();

adapter.DisabledUserById(id);

Repeater1.DataBind();

}

else if (e.CommandName == "Disabled")

{

int id = Convert.ToInt32(e.CommandArgument);

T_UsersStatusTableAdapter adapter = new T_UsersStatusTableAdapter();

adapter.EnabledUserById(id);

Repeater1.DataBind();

}

}

9ListView基础

Repeater一般只用来展示数据,如果要增删改查则用ListView更方便。使用向导(强类型数据)来使用ListView会自动生成很多模板,免去手写模板代码的麻烦,再进行手工调整即可。

首先设定数据源,然后点击智能提示中的”配置ListView”,选择一种布局和样式,然后更具需要勾选”启用编辑”、”启用删除”、”启用插入”、”启用分页”,会自动生成常用的模板。注意这只是提高开发效率的一个快捷方式,不是唯一途径。

LayoutTemplate为布局模板,布局模板中必须有一个ID为itemPlaceholder的服务端控件(4.0以后不需要),什么类型无所谓,不会被显示,itemPlaceholder前面就是相当于Repeater中的HeaderTemplate,itemPlaceholder后面就相当于Repeater中的FooterTemplate,因此ListView中没有这两个模板。

ItemTemplate是偶数行显示的模板;

AlternatingItemTemplate是奇数行显示模板,和Repeater一样;

EmptyDataTemplate为数据源没有数据时显示的内容,这样的话可以实现”没有查询结果”,”对不起,找不到您要找的数据”等;

InsertItemTemplate为插入数据界面的模板;

EditltemTemplate为编辑数据的模板;

SelectedItemTemplate为标记Selected的行的模板。

需要进行微调的地方:

1.         生成的样式要提到style中,不要内联样式。

2.         ItemTemplate里面一般也没有必要用<asp:Label>展示只读数据,所以直接输出<%#eval_r(“Name”)%>。

3.         LayoutTemplate中必须有一个id为ItemPlaceholder的服务端控件,之上为表头,之下为表尾。

4.         LayoutTemplate表头内容要汉化;所有Template中的不需要用户所见的字段,比如Id,都要删掉。

10ListView事件

EditItemTemplate、InsertItemTemplate中控件的绑定表达式为Text=’<%#Bind(“Age”)%>’,因为Eval只是计算表达式的值输出,而Bind不仅可以将计算表达式的值输出,还有将用户填入的值更新到数据中,因此Eval是单向绑定,Bind是双向绑定。

通过每行的Insert、Delete、Edit、Cancel等Command进行增删改,这几个CommandName被ListView内部处理,不需要开发人员处理,因此自定义的CommandName不要和他们重复。ListView中可以像Repeater那样为行增加Command按钮,处理方法和Repeater一样,ListView也支持Repeater那样的ItemDataBound事件。

使用ListView与Repeater的不同地方:

1、  开始的时候,需要判断数据行的类型,e.Item.ItemType == ListViewItemType.DataItem;

2、  强类型DataSet中,取得对应的DataRowView,需要先强制转换成ListViewDataItem类型。

ListViewDataItem lvDataItem = (ListViewDataItem)e.Item;

DataRowView rowView = (DataRowView)lvDataItem.DataItem;

3、在FindControl的时候注意AlternatingItemTemplate的问题。

例子:根据Age字段变色。

protected void ListView2_ItemDataBound(object sender, ListViewItemEventArgs e)

{

if (e.Item.ItemType == ListViewItemType.DataItem)

{

ListViewDataItem lvDataItem = (ListViewDataItem)e.Item;

DataRowView rowView = (DataRowView)lvDataItem.DataItem;

var userRow = (WebApplication1.母版页.DAL.ListViewDataSet.T_UsersRow)rowView.Row;

if (userRow.Age > 20)

{

HtmlTableRow trRow = (HtmlTableRow)e.Item.FindControl("trRow");

trRow.Attributes["class"] = "warning";

}

}

}

其中,需要修改AlternatingItemTemplate和ItemTemplate中<tr>为<tr runat = “server” id = “trRow”>。一个是奇数行,一个是偶数行,均需要修改,而且在模板中,不存在id重复的问题。

ListView中可以使用Validator(验证控件),只要将Validator放入相应的模板中,将Validator手动设为要验证的控件的Id,然后设定相应按钮、控件,Validator为同样的ValidationGroup属性,防止不同模板中的Validator互相干扰。一般设置Cancel按钮为CausesValidation = ”false”属性值,这样取消就不会影响到提交表单。

新增数据行的默认值:响应ListView的ItemCreated事件(每创建一行就会触发这个事件),当e.Item.ItemType为InsertItem的时候通过FindControl找到控件然后初始化。

例:给年龄默认值。

protected void ListView2_ItemCreated(object sender, ListViewItemEventArgs e)

{

if(e.Item.ItemType==ListViewItemType.InsertItem)

{

TextBox txtAge = (TextBox)e.Item.FindControl("AgeTextBox");

txtAge.Text = "20";

}

}

插入数据的初始化:注意和“新增数据行”不同,“插入数据的初始化”是在用户点击“插入按钮”之后执行。比如如果主键为Guid,则需要在数据插入数据库之前为主键赋值。响应ListView的ItemInserting事件(将一些插入数据库之前的对数据进行调整的代码放在这个事件里面)。

e.Values为所有字段的键值对,可以读取插入的值,也可以向字段中写值,这样就可以为Id赋值e.Values[“Id”] = Guid.NewGuid();在这个事件中对数据进行校验,可以通过e.Cancel = true来取消非法数据插入。

ObjectDataSource绑定Id为Guid类型的表的时候会生成一个“DataObjectTypeName = “System.Guid””,有问题,删掉就行,是一个Bug。

11ListView事件2

更新之前的处理:就像数据插入前可以在ItemInserting事件中处理一样,可以在ItemUpdating事件中对更新过程进行处理,e.ItemIndex可以取到当前更新行的行号,e.OldValues可以取到更新前得值,e.NewValues可以取到更新后的值,可以通过e.Cancel = true来取消非法数据插入。

12DropDownList的绑定

ListView是无法像TextBox等控件那样将DropDownList的选中值绑定到数据的字段的,必须编程处理。例子:人员的性别(男、女、保密),三个值固定写在DropDownList中。

1.         在显示数据的时候,DropDownList显示数据的值。在ItemTemplate中加入DropDownList,设定DropDownList.Enabled = ”false”,这样就是只读的。在ItemDataBound事件中e.Item.FindControl()来找到DropDownList控件,然后ListViewDataItem lvDataItem = (ListViewDataItem)e.Item;DataRowView rowView = (DataRowView)lvDataItem.DataItem;取到DataRowView进而取到DataRow,读取数据的值,然后赋值给DropDownList的SelectedValue属性。

2.         在插入数据的时候设定DropDownList对应的字段的值,响应ItemInserting事件,通过e.Item.FindControl找到DropDownList控件,然后通过e.Values设定值。

3.         在数据更新的时候设定DropDownList对应的字段的值,响应ItemUpdatating,通过ListViewDataItem dataItem。

在<EditItemTemplate>中摆放一个DropDownList控件。

<asp:DropDownList runat="server" ID="ddlGender">

<asp:ListItem Value="Male">男</asp:ListItem>

<asp:ListItem Value="Female">女</asp:ListItem>

</asp:DropDownList>

在更新的时候显示DropDownList,在ItemUpdating事件中响应。

protected void ListView2_ItemUpdating(object sender, ListViewUpdateEventArgs e)

{

DropDownList ddlGender = (DropDownList)ListView2.Items[e.ItemIndex].FindControl("ddlGender");

//这里只能通过ListView2.Items[e.ItemIndex].FindControl()找到控件,因为e.Item点不出来FindControl()

e.NewValues["Gender"] = ddlGender.SelectedValue;

}

在编辑的时候显示DropDownList,并通过数据库中存在的值,给DropDownList赋初值。

protected void ListView2_ItemCreated(object sender, ListViewItemEventArgs e)

{

if (e.Item.ItemType == ListViewItemType.DataItem)

{

DropDownList ddlGender = (DropDownList)e.Item.FindControl("ddlGender");

//因为ListViewItemType中只有三个选项,所以选取DataItem并不能准确定位到底是哪一个行,没有Repeater中设定的那么细致,所以这里如果没有获取到ddlGender,则说明不是编辑行。

if (ddlGender != null)

{

ListViewDataItem lvDataItem = (ListViewDataItem)e.Item;

DataRowView rowView = (DataRowView)lvDataItem.DataItem;

//原理与上面相同。

if (rowView != null)

{

var userRow = (theme.ListView.DAL.ListViewDataSet.T_UsersRow)rowView.Row;

ddlGender.SelectedValue = userRow.Gender;

}

}

}

}

13友情链接管理练习说明

需求:后台提供友情链接增删改的页面。友情链接字段:序号、网站名、友情链接类型(图片、文本)、Login地址、链接地址。要进行数据的非空校验等非法值校验,对数据的长度也要校验;序号必填且必须为整数,网站名必填,链接地址必填;当友情链接类型为文本超链接的时候Logo地址隐藏并且可以为空,当友情链接为图片超链接的时候Logo地址显示并且必填。

14友情链接练习点评

主要是为了处理DropDownList,如果除去DropdownList,这个程序就很简单了。在Updateting事件中,取DropDownList控件的方法不一样。主要代码如下:

protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)

{

if (e.Item.ItemType == ListViewItemType.DataItem)

{

DropDownList ddlLinkType = (DropDownList)e.Item.FindControl("ddlLinkType");

ListViewDataItem lvDataItem = (ListViewDataItem)e.Item;

DataRowView rowView = (DataRowView)lvDataItem.DataItem;

if (ddlLinkType != null && rowView != null)

{

var linksRow = (FriendlyLink.DAL.FriendlyLink.T_LinksRow)rowView.Row;

ddlLinkType.SelectedValue = linksRow.LinkType;

}

}

}

protected void ListView1_ItemUpdating(object sender, ListViewUpdateEventArgs e)

{

//必须绕一圈再能取到DropDownList,站在ListView的角度。

DropDownList ddlLinkType = (DropDownList)ListView1.Items[e.ItemIndex].FindControl("ddlLinkType");

e.NewValues["LinkType"] = ddlLinkType.SelectedValue;

}

protected void ListView1_ItemInserting(object sender, ListViewInsertEventArgs e)

{

//不需要绕圈子,直接从Insert行的角度去取DropDownList。

DropDownList ddlLinkType = (DropDownList)e.Item.FindControl("ddlLinkType");

e.Values["LinkType"] = ddlLinkType.SelectedValue;

}

在ListView中给每一行,添加JavaScript代码,需要在ItemCreated事件中更改,因为Insert行不走ItemDataBound事件。

protected void ListView1_ItemCreated(object sender, ListViewItemEventArgs e)

{

if (e.Item.ItemType == ListViewItemType.DataItem || e.Item.ItemType == ListViewItemType.InsertItem)

{

DropDownList ddlLinkType = (DropDownList)e.Item.FindControl("ddlLinkType");

if (ddlLinkType != null)

{

ddlLinkType.Attributes["onchange"] = "onLinkTypeChange(this)";

}

}

}

15入库单练习说明

需求:提供入库明细的增删改查页面。字段:Id(Guid类型)、类型(可选值:采购入库、盘盈入库、退货入库,值来自于另外一张入库单类型表)、入库日期(默认为当天)、单价、数量、金额。所有字段都不能为空,当用户输入单价或者数量之后自动计算金额(金额=单价*数量),考虑折扣因此金额可以不等于数量*单价,用户还可以修改金额。点击【删除】按钮的时候提示用户是否删除。如果数量为负值(红单),则此行显示为红色背景。

16入库单管理练习说明

17行命令处理

ListView的行按钮和Repeater一样,不同的是取当前行数据的方式。int index = ((ListViewDataItem)e.Item).DisplayIndex去取操作行的行号,ListView1.DataKeys[index].Value取出主键的值(DataKeys中存放了所有主键的值)。如果对数据进行了操作,最后要执行ListView .DataBind刷新数据。

案例:涨一岁按钮。

protected void ListView1_ItemCommad(object sender,ListViewCommandEventArgs e)

{

int index = ((ListViewDataItem)e.Item).DisplayIndex;

Guid id = (Guid)ListView1.DataKays[index].Value;

//以上两行代码实现了取出主键。

if(e.CommandName == “IncAge”)

{

T_personsTableAdapter adapter = new T_personsTableAdapter();

adapter.IncAge(id);

ListView1.DataBind();

}

}

ListView1.DataKays[index]还有一个Values方法,可以取出多个值,但是需要在ListView的DataKeyName属性中设定,默认只存Id,可以添加、修改,如果添加了多个值,则需要使用Values来取值。例:ListView1.DataKays[index].Values[“Id”];

排序:将LayoutTemplate中的表头放一个按钮控件,如:<asp:LinkButton runat = “server” CommandName = “Sort” CommandArgument=”Id” Text = “Id” />(可以用这个控件代替表头字段),其中CommandArgument的值是排序依据的字段,此处是依据Id排序;CommandName的值必须为Sort,这样标志这进行排序。只要是CommandName、CommandArgument对就行,展现成什么、显示在哪儿都可以。

这种内置的排序,是把所有的数据都遍历了再进行排序,所以效率是相当低的,在互联网应用程序中不推荐使用。

18ListView分页基础

DataPager

ListView搭配<DataPager>控件实现分页。有两种方式,一种是将DataPager声明到ListView中;另一种是DataPager、ListView没有嵌套关系,然后将DataPager的PagedControlID设定为要分页的ListView的ID。没有什么区别,一般用“配置ListView”自动生成的内置方式即可。DataPager的PageSize属性为一页得条数。

(*)理论上实现IPageableItemContainer接口的控件都可以使用DataPager进行分页,但是ASP.Net内置的控件目前只有ListView实现了这个接口。

DataPager中按钮显示风格由Fields中的字段设置,可以设置多个字段,分为“NextPreviousPageField”(上一页、下一页、首页、末页等)、“NumericPAgerField”(数字页号)、“TemplatePagerField”用模板自定义。代码中选择相应的Field,在【属性视图】中就可以快速修改它们的属性。

DataPager调整

相关单词:First:第一;Last:最后;Next:下一个;previous:上一个。

NextPreviousPagerField(上下页)主要属性:ButtonCssClass:按钮的样式;ButtonType:按钮渲染成什么(Button按钮、Link超链接、Image图片);FirstPageImageUrl:【第一页】按钮图片地址;FirstPateText:【第一页】按钮文本,这样可以实现上一页显示为“<”,最后一页显示为“>>”这样的效果;ShowFirstButton:是否显示【第一页】,其他按钮也有对应属性。

NumericPagerField(数字分页)主要属性:ButtonCount:最多显示数字的个数;ButtonType:按钮渲染成什么(Button按钮、Link超链接、Image图片);CurrentPageLabelCssClass当前页文本的样式;NumericButtonCssCalss数字按钮的样式。

如何实现|<</</页数/>/>>|这样的效果。顺序添加NextPreviousPagerField、NumericPagerField、NextPreviousPagerField,将第一个NextPreviousPagerField的First、Previous设置为可见,Last、Next设置为不可见,将最后一个NextPreviousPagerField的First、Previous设置为不可见,Last、Next设置为可见。

(*)实现输入页面编号点击跳转或者在下拉列表中选择页数要用TemplatePagerField。

19ListView高效分页

ListView默认的分页是先从数据源取得所有数据,然后再截取当前页面的部分,在数据量非常大的情况下效率非常低,因此默认分页基本上不能用。应该是只从数据源取得要显示的数据。

复习:SQL中语句中取得分页数据。SQL语句中获得每一行序号的方法:

select id,SiteName,LogoURL,Row_Number() over(order by Id) as rownum from T_Links;

Row_Number()函数是SQL2005之后提供的一个计算结果集行号的函数(不是表的行号),over中指定排序依据,Row_Number()从1开始。取得第11条至20条数据(条数从0开始)的方法,使用子查询用行号进行再次处理:

select * from

(select Id,SiteName,LogoURL,row_number() over(order by Id) as rownum

from T_Links ) as t

where t.rownum>11 and t.rownum<=20.

在强类型DataSet中增加取得所有数据条数的方法QueryCount:

select * from T_Links

,增加取得指定行数范围数据的方法GetPagedData:

select * from

(select …,row_number() over(order by …) as rownum from T_Links) as t

where t.rownum>@startRowIndex and t.rownum<[email protected][email protected]

由于数据集编辑器不支持ron_number()(不是运行时不支持,只是设计器不会自动帮我们生成一些东西),所以创建完成后需要手动在【GetPagedData属性】的Parameters属性中增加两个参数:StartRowIndex、maximumRows(参数名必须是这两个,这是由ObjectDatSource的StartRowIndexParamterName、MaximumRowsParamterName确定的,一般不需要修改),都是int32类型。

操作顺序:

先按正常的流程配置ObjectDataSource,让ListView自动生成Template,再修改ObjectDataSource的EnablePaging=”True”,SelectCountMethod设置为取得行数的方法。否则很多自动生成的东西都没有生成。

ObjectDataSource中EnablePaging属性设置为true,SelectCountMethod设置为QueryCount,SelectMethod设置为GetPagedData。

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

DeleteMethod="Delete" EnablePaging="True" InsertMethod="Insert"

OldValuesParameterFormatString="original_{0}" SelectCountMethod="QueryCount"

SelectMethod="GetPagedData"

TypeName="Paging.DAL.PagingTableAdapters.T_UsersTableAdapter"

UpdateMethod="Update">

详细查看Paging程序。

如果出错的话看看是不是没有放置内置的DataPager或者外置的DataPager的Page地ControlID没有指向ListView。

DatPager默认是用PostBack机制,显示不到地址中,不利于网络间共享,只要指定QueryStringField属性(比如Pagenum)就可以实现超连接形式的分页链接。

(*)GetPagedData中的StartRowIndex、maximumRows两个参数名其实是可以修改的,但是一般不推荐去修改它们。在【ObjectDataSource属性】中,有两个属性StartRowIndexParam、MaximunRowsParam分别对应着这两个参数。

20行的单独页编辑

ListView的数据编辑只适合字段比较少、比较简单的场合,复杂数据的编辑、插入、查看等要在单独页面中完成(FormView控件)。

创建一个单独的页面Edit*.aspx,然后在ListView页面中的编辑一个编辑的超链接,向Edit*.aspx传递?id=1&action=edit。页面顶端增加一个Edit*.aspx?action=addnew的超链接。

使用FormView控件进行单条数据的编辑,在Page_Load中判断action,然后使用FormView1.ChangeMode方法切换FormView的模式。

在元素插入、修改完成(Inserted、Updated事件)后重定向到列表页面。

当把<ListView>的属性设置为InsertItemPosition=”None”,则不显示插入模板,这样如果数据库为空,则能显示“EmptyTemplate”中的值。所以一般有插入模板的时候,是不会显示<EmptyTemplate>模板中的值的。

FormView用来进行单行的编辑、查看、新增,有编辑、查看、新增三个模板。

在FormView中可以自己写按钮来切换这三个模板。切换为新增模板,使用

FormView1.ChangeMode(FormViewMode.Insert);

FormView有三个模式:FormViewMode.Edit:编辑模式;FormViewMode.Insert:插入模式;FromViewMode.ReadOnly:只读模式。

强类型DataSet中增加一个GetDataById方法,在ObjectDataSource中选择这个方法为Select参数,参数源为QueryString(查询字符串,用于get传值),QueryStringField为id(表示传入Id字段的值)。

21行的单独页面编辑2

在单独页中需要调整的代码:

1、  删除Id,需要在ItemInserting事件中为Id赋值。(e.Values[“Id”] = Guid.NewGuid();//Guid算法)

2、  插入完成、更新完成以后重定向到ListUI界面。需要在ItemInserted和ItemUpdated事件中进行修改。(Response.Redirect(“ListUI.aspx”);)

JqueryUI.js在JQuery.js之后引入,否则会出错。

22行的单独页面编辑3

响应FormView的ItemCreated事件,用FormView1.CurrentMode判断当前渲染的模板(因为FormView同时只能渲染一个模板,不需要像ListView那样e.Item.ItemType)。然后用FormView1.FindControl找到控件(也不像ListView中用e.Item.FindControl();)。

插入的时候使用DropDownList,与在ListView控件中使用,思路是一样的。

23CKEditor的使用

CKEditor原名FckEditor,著名的HTML编辑器(常见的发帖控件),可以在线编辑HTML内容。

配置参考文档,主要将ckeditor中的(adapters、images、lang、plugins、skins、themes、cheditor.js、config.js、content.css)解压到js目录,在发帖页面引用ckeditor.js,然后设置多行文本框的class = “ckeditor”(服务端控件改CssClass=” ckeditor”),代码中仍然可以通过TextBox控件的Text属性来访问编辑器内容。

由于页面提交的时候asp.net会把副文本编辑器中的html内容当成攻击内容,因此需要在aspx中的Page标签中设置ValidateRequest=”false”来禁用攻击检测。(VS2010中还有更具报错信息修改WebConfig来禁用XSS)

24CKFinder的集成

CKFinder是一个CKEditor插件,用来为CKEditor提供文件的上传的功能。将bin/Release下的CKFinder.dll添加到项目的引用;将core、ckfinder.js、ckfinder.html、config.aspx解压到CKFinder自己的目录。按照文档修改CKEditor的config.js,将上传的处理程序设定为CKFinder,注意路径的问题。

因为上传文件是非常危险的动作,因此在文件上传的时候会进行权限校验。在config.ascx的CheckAuthentication方法中校验是否有上传权限,返回true表示有权限,返回false没有权限,一般修改成判断用户是否登录,并且登录用户是有上传权限的用户,可以用Session或者Membership来做。思考:如何实现只有指定IP地址的用户才能上传?

public override bool CheckAuthentication()

{

object obj = Session[“登录”];

if(obj != null && Convert.ToBoolean(obj) == true)

{

return true;

}

reture false;

}

在SetConfig函数中设置上传文件夹的位置BaseUrl、缩略图的位置,每种类型数据的上传路径、允许上传的文件类型AllowedExtensions等。

type.AllowedExtensions = new string[]{“bmp”,”gif”,”jpeg”};

25入库单管理练习点评及.Net4.0Bug解决

在服务端使用ClientID是无法找到正确的模板ID的。这是4.0的一个Bug,在3.5的环境下就不会存在这样的问题。

方法一:在服务端使用ClientID获得的ID与模板ID比较缺少的只是”ListView1_”,可以在服务端代码,获得控件ID的时候手动的添加这个字符串。

方法二:在模板控件中定义一个额外的属性“myid”,然后在JQuery中,使用属性选择器$(“input[myid=”+countMyId+”]”).val();得到控件的值。

方法三:修改ListView的ClientIDMode属性。

26综合案例企业网站1

27企业网站2

28企业网站练习点评

29企业网站练习点评2

30禁用ViewState

默认情况下ASP.Net是启用ViewState的,这样在页面中会生产很长的隐藏字段,ViewState对于需要PostBack处理的页面也可能有用,对于新闻展示页面完全没必要用ViewState。

禁用ViewState的方法:

页面整体禁用ViewState:在顶部Page中添加“EnableViewState=”False””。

指定控件禁用ViewState:在控件上“EnableViewState=”False””。

页面禁用ViewState以后并没有完全去掉ViewState,只要ViewState不是很大就可以。如果要求一点ViewState都不能有,那么则页面中不能有runat = “server”的form,如果页面中没有表单元素,把form完全去掉就可以。如果Button等服务端控件没有放到runat = “server”的form中,那么则是不可用的。

31缓存1(cache

如果每次进入页面的时候都查询数据库生成页面内容的话,如果访问量非常大,则网站性能会非常差。而如果只有第一次访问的时候才查询数据库生成页面内容,以后都直接输出内容,则能提高系统性能,这样无论有多少人访问都只访问一次数据库,数据库压力不变,就算有很多人访问,只是增加了服务器的压力。

缓存是一种用空间换取时间的技术,存在于计算机中很多地方,用来将一些慢速设备中的常用数据保存在快速设备中,去取数据的时候直接从快速设备中取。比如CPU二级缓存、windows文件读取缓存。

缓存存在失效的问题:为了保证从缓存中读取数据和慢速数据中数据一致,则需要在慢速数据中对应的数据发生变化的时候,清除缓存中相应的数据。

换成是改进网站性能的一个手段,就像索引是改进数据库性能的一个手段一样。ASP.Net缓存主要分为:页面缓存、数据源缓存、数据缓存这三种主要类型。

32缓存2

页面缓存

给页面添加<%@OutputCache Duration=”15” VaryByParam = “none”%>标签就可以启动页面缓存,这样整个页面的内容都会被缓存,页面中的ASP.Net代码、数据源在缓存期间都不会被运行,而是直接输出缓存的页面内容。Duration表示缓存事件,以秒为单位,超过这个事件则缓存失效,再次生成以后会再缓存15秒,以此类推。在Page_Load处设置断点,修改数据库数据测试。

缓存是针对所有这个页面的访问者。这样1个访问者和1万个访问者,一次访问和100万次访问数据库的压力是一样的。

对于看新闻页面来讲,如果如上设置的话,则会缓存在第一个看到的新闻,因为?id=2、?id=3只是页面的不同参数而已,为了能让不同的新闻各自缓存,因此可以设置VaryByParam=”id”,表示对于不同的id参数进行单独缓存。如果有多个确定缓存的参数,则将参数名用分号隔开即可,比如:VaryByParam = “id,number”。

如果想让任何不同的查询字符串都创建不同的缓存,则设置VaryByParam=”*”,一般情况下设置”*”就足够。

在WebUserControl中也可以像页面缓存一样设置控件的缓存。

数据源缓存

设定ObjectDataSource的CacheDuration(缓存时间:秒),EnableCaching = true;。这样每隔CacheDuration指定的时间段才调用SelectMethod指定的方法来执行数据库查询,其他时候都是直接返回缓存的数据。

缓存固定的事件适用于首页、文章列表等访问频繁的页面,对于看帖页面则不适合,假设有100万个帖子,如果每隔帖子都是固定缓存1小时的话,假设一小时内有10万个帖子被看了,那么就要缓存十万个帖子,非常占用内容,因为“百年一看”的“坟贴”偶然被访问一次也缓存一个小时,占用内存。这时候可以采用“滑动窗口”策略,比如帖子缓存10分组,如果10分钟之内又访问了,则缓存的失效事件修改为从被访问这一刻起的10分钟之后,以此类推。这样经常访问的帖子就可以“长期缓存”,而不经常访问的帖子也不会因为偶然访问而长期占用缓存。设置方法,数据源:CacheExpirationPolicy = “Sliding”

33错误页1

当页面发生错误的时候,ASP.Net会将错误信息展示出来,这样一来不好看,二来会泄露网站的内部实现信息,给网站带来安全隐患,因此需要定制错误页,发生错误时显示开发人员定制的页面。404页面放点广告也好嘛,反正流量也浪费了。

配置web.config,配置custonErrors区域:

<custonErrors mode = “RemoteOnly” defaultRedirect = “GenericErrorPage.htm”>

<error statusCode = “403” redirect = “NoAccess.htm”>

<error statusCode = “404” redirect = “FileNotFound.htm”>

</custonErrors>

mode三个可选值:On,总是显示定制错误页面;Off,不显示定制错误页面,直接显示调用堆栈等异常信息;remoteOnly,对于本机的访问显示调用堆栈等异常信息,对于外部的用户显示定制错误页。一般设置为RemoteOnly,这样发生错误的话,管理员可以在服务器的浏览器中看到详细错误信息,普通用户看不到。学习掩饰的时候mode设置为On,否则看不到定制错误页。

也可以在定义错误页中判断Request.UserHostAddress来设置某些ip看到异常信息,可以读取Session,如果是管理员则看异常信息。

34错误页2

error子元素设定对于不同的状态码使用不同的错误页,很多网站都把404做一个特殊的错误页。没有单独设置的状态码错误则显示defaulyRedirect中指定的页面。

错误也既可以使用htm页面,也可以使用aspx页面。在aspx页面中可以用HttpContext.Current.Server.GetLastError()拿到异常对象。一般不要把异常信息显示给用户,而是使用后面讲的Log4Net等将异常记录到系统日志。

如果要在错误页面中拿到异常对象,需要在<custonErrors>中设置redirecrMode = “RespinseRewrite”,因为默认是客户端重定向,在错误页面中就拿不到异常对象了。

控件绑定

时间: 2024-11-10 14:41:40

控件绑定的相关文章

DataGridView控件绑定数据源

前言: 最近听说DataGridView控件能直接绑定数据源.而不用穿越这层那层的忍辱负重.获取数据.真是高兴的屁颠屁颠的.后来一想二狗肯定不会弄.特意写了一个笨蛋版的教程--也算记录生活.欢度端午了.粽子就不送给大家了.但是大家可以找我来要呦!数量有限送完为止!--chenchen --步骤 1 添加控件 2 添加数据源 中间过程就是点下一步就不截图了.最后选择的这个是每次连接获取数据库数据的表和表的字段 3 三个组件意思 Adapter控件:连接数据库获取数据 DataSet:存放获取好的数

vue2.0 之表单控件绑定

表单控件绑定v-model 1.文本 <template> <div> <input type="text" name="" v-model="myVal"><br/> {{ myVal }}<br/> <input type="text" name="" v-model.lazy="myVal1"><br/&

Asp.net--DropDownList控件绑定数据库数据

DropDownList控件绑定数据库数据:DB是公共类,reDt是公共类中的方法 放在Page_Load事件中 if (!IsPostBack) { DB db = new DB(); DataTable dt = db.reDt("select * from provinceInfo order by provinceid asc"); ddlsmprovince.DataSource = dt; ddlsmprovince.DataTextField = ddlsmprovinc

对话框控件绑定变量及操作

对话框控件绑定变量 右键单击控件,添加变量. 复选框:添加变量为控件变量.可以操作控件. 列表框:选择添加变量的控件的ID. 列表框:选择添加的变量的类别,Control为控件控制类型.Value为关联值变量,可以设置数据验证 编辑框:添加的控件变量名. 复选框:不选中,则为控件关联一个变量.不可以操作控件. 列表框:选择关联变量类型. 编辑框:添加的控件变量名.  头文件中添加的变量 // CMFCTestDlg dialog class CMFCTestDlg : public CDialo

C# Winform 关于ListView控件绑定DataTable

今天用到ListView控件,这里总结一下ListView控件绑定DataTable的方法 下面需要特别注意的是,绑定的过程中实现绑定控件的column的属性,再进行item的绑定. 与DataGridView不同的是,不能直接使用DataSourse绑定, 再者,绑定第一个Items的时候一定要实例化一个Item进行单独绑定,因为第一个Item与后面的不用即Item与SubItem的区别,下面的代码中也给出了相应的注释 [csharp] view plain copy private void

vue.js基础知识篇(3):计算属性、表单控件绑定

第四章:计算属性 为了避免过多的逻辑造成模板的臃肿不堪,可使用计算属性来简化逻辑. 1.什么是计算属性 <!DOCTYPE html> <html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <div id="example"> <

c#中DropDownList控件绑定枚举数据

c# asp.net 中DropDownList控件绑定枚举数据 1.枚举(enum)代码: private enum heros { 德玛 = 0, 皇子 = 10, 大头 = 20, 剑圣 = 30, } 如果不为枚举数列表中的元素指定值,则它们的值将自动递增,从1开始. 2.cs代码: private void LoadData() { //检索枚举heros返回包含每个成员的值的数组 Array herosArray = Enum.GetValues(typeof(heros)); fo

关于vue.js中表单控件绑定练习

html: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>表单控件绑定</title></head><body> <!-- v-model在表单控件元素上实现数据的双向绑定 --> <div id="app-1"> <input ty

在aspx页动态加载ascx页面内容,给GridView控件绑定数据

在aspx页动态加载ascx页面内容 //加载ascx页面内容Control c1 = this.Page.LoadControl("WebUserControl1.ascx");//绑定到aspx页的PlaceHolder控件上PlaceHolder1.Controls.Add(c1); DataSet ds = SqlServerHelpr.GetDataSet("select * from dbo.Table_1");//给GridView控件绑定数据Grid

Silverlight项目笔记5:Oracle归档模式引起的异常&amp;&amp;表格控件绑定按钮

两个问题: (1)Oracle无法连接正常使用,原因是归档日志满了引起异常,最后选择删除归档日志恢复正常. (2)使用silverlight自带的表格绑定按钮竟然无法使用,通过变通绑定数据源集合,把按钮操作作为数据源集合一部分,重新绑定解决. 一.Oracle归档模式产生日志文件引起数据库异常 连接数据库失败,提示监听错误,各种检查监听配置文件,删除再添加监听,无果. sqlplus下重启数据库数据库依然无果,期间碰到多个错误提示: ORA-01034: ORACLE not available