您的位置:首页 > 编程语言 > ASP

可用于多行分数编辑的 Asp.net UserControl (能够实现可多行编辑,并汇总的自定义Grid控件)

2010-09-14 17:45 295 查看
1. 问题的提出:

一种的动态的分数修改控件,可以添加新的记录行,而且可以编辑每行中的评价项名称,和分数,并且能够汇总分数。考虑到如果用GridView等控件实现,无法做到插入新记录行,所以需要用到自定义控件。

在开发时候,起初直接构建Table对象,添加TableCell,结果发现服务端对象在每次提交页面时候,重新被初始化,即Table对象需要被保存。如果用Session的方式,需要保存Table对象,分数集合,总分数等多个属性,尤其在实现复选框事件,和动态增加的文本框事件时,越开发越烦,所以彻底抛弃了原来的方式。

2. ListView控件的使用

关于ListView的基本使用,可以参考MSDN的帮助。ListView 可以用子控件和数据源绑定的方式来呈现数据,这是非常好的一种思路。对于实现可以自定义的多行编辑控件,就更能省下很多力气的。

本文的实现特借鉴一篇E文的文章,所以特专门写出:
http://geekswithblogs.net/QuandaryPhase/archive/2008/10/19/asp.net-alternatives-to-dynamic-controls---part-1.aspx
2.1 自定义控件的页面代码:

<div id="divTable" runat="server">
<asp:ListView ID="lvDynamicTextBox" runat="server" ItemPlaceholderID="itemPlaceholder" OnItemDataBound="lvDynamicTextboxes_ItemDataBound">
<LayoutTemplate>
<table>
<tr style="background-color:Olive">
<td>
</td>
<td>
</td>
<td>序号</td>
<td>名称</td>
<td>分数</td>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
<tr style="background-color:Olive">
<td>
</td>
<td>
</td>
<td></td>
<td align="right">总分数:</td>
<td><asp:label id="lblSumScore" runat="server"/></td>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="lblKey" runat="server" Visible="false" />
</td>
<td>
<asp:CheckBox ID="chkSelect" runat="server" AutoPostBack="true" />
</td>
<td>
<asp:Label ID="lblOrderNumber" runat="server"></asp:Label>
</td>
<td style="width:60%">
<asp:TextBox ID="txtName" runat="server" Width="100%"></asp:TextBox>
</td>
<td style="width:20%">
<asp:TextBox ID="txtScore" runat="server" Width="100%" AutoPostBack="true" ontextchanged="txtScore_TextChanged"></asp:TextBox>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
</div>

2.2 自定义控件的后端代码:

/// <summary>
/// 可编辑的Grid控件
/// </summary>
public partial class GirdEditControl : System.Web.UI.UserControl
{
public event EventHandler<ScoreChangedEventArgs> OnScoreChanged;

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.BindListView();
}
}

/// <summary>
/// 插入
/// </summary>
/// <param name="scoreItem"></param>
public void Insert(ScoreItem scoreItem)
{
UpdataDataSource();
IncrementTextboxCount(scoreItem);
BindListView();

//重新排序号
ReDisplayOrderNumber();
}

/// <summary>
/// 删除
/// </summary>
public void Delete()
{
List<ScoreItem> dataSource = this.GetDataSource();
foreach (ListViewItem item in this.lvDynamicTextBox.Items)
{
if (item is ListViewDataItem)
{
CheckBox chk = (CheckBox)item.FindControl("chkSelect");
if (chk.Checked == true)
{
ScoreItem scoreItem = CreateScoreItem((ListViewDataItem)item);
dataSource.Remove( dataSource.Find(p => p.Key == scoreItem.Key));
}
}
}
SetDataSource(dataSource);
BindListView();

//重新排序号
ReDisplayOrderNumber();
}

/// <summary>
/// 重新排序号
/// </summary>
private void ReDisplayOrderNumber()
{
int count = this.lvDynamicTextBox.Items.Count;
for (int i = 0; i < count; i++)
{
ListViewItem item = this.lvDynamicTextBox.Items[i];
if (item is ListViewDataItem)
{
((Label)item.FindControl("lblOrderNumber")).Text = (i + 1).ToString();
}
}
}

/// <summary>
/// 获得总分数
/// </summary>
/// <returns></returns>
public double GetScoreSum()
{
double scoreSum = 0;
List<ScoreItem> dataSource = this.GetDataSource();
if (dataSource != null)
{
scoreSum = dataSource.Sum(p => p.Score);
}
return scoreSum;
}

/// <summary>
/// 获得分数的记录集合
/// </summary>
/// <returns></returns>
public List<ScoreItem> GetDataList()
{
return this.GetDataSource();
}

//绑定
private void BindListView()
{
List<ScoreItem> dataSource = this.GetDataSource();

this.lvDynamicTextBox.DataSource = dataSource;
this.lvDynamicTextBox.DataBind();

DisplaySumScore(dataSource);
}

/// <summary>
/// 显示总分数
/// </summary>
/// <param name="dataSource"></param>
private double DisplaySumScore(List<ScoreItem> dataSource)
{
double scoreSum = 0;
if (dataSource != null)
{
scoreSum = dataSource.Sum(p => p.Score);
((Label)lvDynamicTextBox.FindControl("lblSumScore")).Text = scoreSum.ToString();
}
return scoreSum;
}

/// <summary>
/// 更新数据源
/// </summary>
private void UpdataDataSource()
{
ScoreItem scoreItem;
List<ScoreItem> dataSource = new List<ScoreItem>();
foreach (ListViewItem item in this.lvDynamicTextBox.Items)
{
if (item is ListViewDataItem)
{
scoreItem = CreateScoreItem((ListViewDataItem)item);
dataSource.Add(scoreItem);
}
}
this.SetDataSource(dataSource);
}

/// <summary>
/// 创建分数记录对象
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private ScoreItem CreateScoreItem(ListViewDataItem item)
{
Label lbl = (Label)item.FindControl("lblKey");
string strKey = lbl.Text;

lbl = (Label)item.FindControl("lblOrderNumber");
string strOrderNumber = lbl.Text;

TextBox txt = (TextBox)item.FindControl("txtName");
string strNname = txt.Text;

txt = (TextBox)item.FindControl("txtScore");
string strScore = txt.Text;

ScoreItem scoreItem = new ScoreItem(int.Parse(strKey),
strNname,
int.Parse(strScore));

return scoreItem;
}

/// <summary>
/// 插入文本记录
/// </summary>
/// <param name="scoreItem"></param>
private void IncrementTextboxCount(ScoreItem scoreItem)
{
List<ScoreItem> dataSource = this.GetDataSource();
dataSource.Add(scoreItem);
this.SetDataSource(dataSource);
}

/// <summary>
/// 获取数据源
/// </summary>
/// <returns></returns>
private List<ScoreItem> GetDataSource()
{
List<ScoreItem> dataSource = null;
if (ViewState["DataSource"] != null)
{
dataSource = (List<ScoreItem>)ViewState["DataSource"];
}
else
{
;
}
return dataSource;
}

/// <summary>
/// 设置数据源
/// </summary>
/// <param name="dataSource"></param>
private void SetDataSource(List<ScoreItem> dataSource)
{
ViewState["DataSource"] = dataSource;
}

/// <summary>
/// 分数记录对象与控件绑定事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void lvDynamicTextboxes_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewDataItem)
{
ScoreItem scoreItem = ((ListViewDataItem)e.Item).DataItem as ScoreItem;

Label lblKey = (Label)e.Item.FindControl("lblKey");
lblKey.Text = scoreItem.Key.ToString();

TextBox txtName = (TextBox)e.Item.FindControl("txtName");
txtName.Text = scoreItem.ScoreContent;

TextBox txtScore = (TextBox)e.Item.FindControl("txtScore");
txtScore.Text = scoreItem.Score.ToString();
}
}

/// <summary>
/// 分数记录改变的事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void txtScore_TextChanged(object sender, EventArgs e)
{
UpdataDataSource();
double scoreSum = DisplaySumScore(this.GetDataSource());

if (OnScoreChanged != null)
{
ScoreChangedEventArgs args = new ScoreChangedEventArgs(scoreSum);
OnScoreChanged(null, args);
}
}
}

2.3 主页面上调用

2.3.1 apsx代码

<div>
<asp:Button ID="btnSelect" runat="server" Text="Select"
onclick="btnSelect_Click" />
<asp:Button ID="btnInsert" runat="server" Text="Insert"
onclick="btnInsert_Click" />
<asp:Button ID="btnDelete" runat="server" Text="Delete"
onclick="btnDelete_Click" />
<asp:Label ID="lblScoreSum" runat="server" />
<uc1:GirdEditControl ID="grdScoreEdit" runat="server" />
</div>

2.3.2 后端代码

protected void Page_Load(object sender, EventArgs e)
{
grdScoreEdit.OnScoreChanged += new EventHandler<ScoreChangedEventArgs>(grdScoreEdit_OnScoreChanged);
}

protected void grdScoreEdit_OnScoreChanged(object sender, ScoreChangedEventArgs e)
{
lblScoreSum.Text = string.Format("总分数:{0}", e.ScoreSum.ToString());
}

protected void btnSelect_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
grdScoreEdit.Insert(new ScoreItem(i, "检查"+i.ToString(), 20));
}
}

protected void btnInsert_Click(object sender, EventArgs e)
{
grdScoreEdit.Insert(new ScoreItem(22, "检查", 200));
}

protected void btnDelete_Click(object sender, EventArgs e)
{
grdScoreEdit.Delete();
}

3. 总结

利用ViewState保存数据源对象,避免了使用Session带来的诸多问题。分数的用户控件的功能已经实现,根据该思路,还可以继续扩展。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: