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

来源:互联网 发布:seo与sem 编辑:程序博客网 时间:2024/05/22 16:42

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带来的诸多问题。分数的用户控件的功能已经实现,根据该思路,还可以继续扩展。