我用DataPager与ListView实现分页,想跨页多选,进行记录删除请高手指教

解决方案 »

  1.   

    使用 Entity Framework + ListView + DataPager 实现数据分页http://www.cnblogs.com/btbtshu/articles/1504602.html
      

  2.   

    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <script runat="server">
        protected ArrayList SelectedItems //存储主键
        {
            get
            {
                return (ViewState["mySelectedItems"] != null) ? (ArrayList)ViewState["mySelectedItems"] : null;
            }
            set
            {
                ViewState["mySelectedItems"] = value;
            }
        }
        
        /// <summary>
        /// 从当前页收集选中项的情况
        /// </summary>
        protected void CollectSelected()
        {
            ArrayList selectedItems = null;
            if (this.SelectedItems == null)
                selectedItems = new ArrayList();
            else
                selectedItems = this.SelectedItems;        for (int i = 0; i < this.ListView1.Items.Count; i++)
            {
                Label ll = this.ListView1.Items[i].FindControl("movie_idLabel") as Label;
                string id = ll.Text.Trim();
                CheckBox cb = this.ListView1.Items[i].FindControl("CheckBox1") as CheckBox;
                if (selectedItems.Contains(id) && !cb.Checked)
                    selectedItems.Remove(id);
                if (!selectedItems.Contains(id) && cb.Checked)
                    selectedItems.Add(id);
            }
            this.SelectedItems = selectedItems;
        }    //在每一次重新绑定之前,需要调用CollectSelected方法从当前页收集选中项的情况
        protected void ListView1_DataBinding(object sender, EventArgs e)
        {
            CollectSelected();    }    protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
            //这里的处理是为了回显之前选中的情况
            if(e.Item.ItemType == ListViewItemType.DataItem && this.SelectedItems !=null)
            {
                ListViewItem item = e.Item as ListViewItem;
                CheckBox cb = e.Item.FindControl("CheckBox1") as CheckBox;
                Label ll = e.Item.FindControl("movie_idLabel") as Label;
                
                if (this.SelectedItems.Contains(ll.Text.Trim()))
                    cb.Checked = true;
                else
                    cb.Checked = false;
            }    }
        
        //一页全选 (有点不尽人意)
        protected virtual void OnChecked(Object sender, EventArgs args)
        {
            ArrayList selectedItems = null;
            if (this.SelectedItems == null)
                selectedItems = new ArrayList();
            else
                selectedItems = this.SelectedItems;
                
            CheckBox chkHeader = sender as CheckBox;
            for (int i = 0; i < ListView1.Items.Count; i++)
            {
                CheckBox chk = ListView1.Items[i].FindControl("CheckBox1") as CheckBox;
                Label ll = this.ListView1.Items[i].FindControl("movie_idLabel") as Label;
                chk.Checked = chkHeader.Checked;
                
                if (!selectedItems.Contains(ll.Text.Trim()))//把主键字段存入ArrayList
                    selectedItems.Add(ll.Text.Trim());      
            }
            this.SelectedItems = selectedItems;
            
        }
        
        //删除时
        protected void Button1_Click(object sender, EventArgs e)
        {
            //最后,需要对选中项进行操作之前,不能忘了还要最后一次收集当前页的选中情况
            CollectSelected();        //
            //  在这里可能通过SelectedItems存储的主键删除相应的记录
            //
        }
    </script><html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>ListView CSS-driven grid</title>
        <link href="StyleSheet.css" rel="stylesheet" type="text/css" /></head>
    <body>
        <form id="form1" runat="server">
        <div>
            <ContentTemplate>
            <asp:ListView ID="ListView1" runat="server" DataKeyNames="movie_id" 
                DataSourceID="_moviesDataSource" EnableViewState="False" 
                ondatabinding="ListView1_DataBinding" 
                onitemdatabound="ListView1_ItemDataBound">            
            <LayoutTemplate>        <div class="Pagination">
                <asp:DataPager ID="DataPager2" runat="server" QueryStringField="pageNum" >
                    <Fields>
                        <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" 
                            ShowNextPageButton="False" ShowPreviousPageButton="False" />
                        <asp:NumericPagerField />
                        <asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="True" 
                            ShowNextPageButton="False" ShowPreviousPageButton="False" />
                    </Fields>
                </asp:DataPager>
            </div>
            <div class="PrettyGrid">
                <table cellpadding="0" cellspacing="0" summary="">
                <thead>
                  <tr>
                   <th scope="col"><asp:CheckBox ID="Ck" runat="server" AutoPostBack="true"  OnCheckedChanged="OnChecked"></asp:CheckBox></th>
                    <th scope="col"><asp:LinkButton ID="_movieIdSortLink" CommandName="Sort" 
                          CommandArgument="movie_id" runat="server">ID</asp:LinkButton></th>
                    <th scope="col"><asp:LinkButton ID="_titleSortLink" CommandName="Sort" 
                          CommandArgument="title" runat="server">Title</asp:LinkButton></th>
                    <th scope="col"><asp:LinkButton ID="_releaseDateSortLink" CommandName="Sort" 
                          CommandArgument="release_date" runat="server">Release date</asp:LinkButton></th>
                  </tr>
                </thead>
                <tbody>
                    <asp:PlaceHolder ID="itemPlaceholder" runat="server" />
                </tbody>
                </table>            <div class="Pagination">
                    <asp:DataPager ID="DataPager1" runat="server">
                        <Fields>
                            <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" 
                                ShowNextPageButton="False" ShowPreviousPageButton="False" />
                            <asp:NumericPagerField />
                            <asp:NextPreviousPagerField ButtonType="Button" ShowLastPageButton="True" 
                                ShowNextPageButton="False" ShowPreviousPageButton="False" />
                        </Fields>
                    </asp:DataPager>
                </div>
            
            </div>
            </LayoutTemplate>        <AlternatingItemTemplate>
                <tr class="Alternate">
                <td><asp:CheckBox ID="CheckBox1" runat="server" Checked="False" Text='' /></td>
                    <td>
                        <asp:Label ID="movie_idLabel" runat="server" Text='<%# Eval("movie_id") %>' />
                    </td>
                    <td>
                        <asp:Label ID="titleLabel" runat="server" Text='<%# Eval("title") %>' />
                    </td>
                    <td>
                        <asp:Label ID="release_dateLabel" runat="server" 
                            Text='<%# Eval("release_date", "{0:d}") %>' />
                    </td>
                </tr>
            </AlternatingItemTemplate>  
            
            <SelectedItemTemplate>
             <tr>
                    <td><asp:CheckBox ID="CheckBox1" runat="server" Checked="False" Text='' /></td>
                    <td>
                        <asp:Label ID="movie_idLabel" runat="server" Text='<%# Eval("movie_id") %>' />
                    </td>
                    <td>
                        <asp:Label ID="titleLabel" runat="server" Text='<%# Eval("title") %>' />
                    </td>
                    <td>
                        <asp:Label ID="release_dateLabel" runat="server" 
                            Text='<%# Eval("release_date", "{0:d}") %>' />
                    </td>
                </tr>
            </SelectedItemTemplate>
                      
            <EmptyDataTemplate>
                <table id="Table2" runat="server">
                    <tr>
                        <td>
                            No data was returned.</td>
                    </tr>
                </table>
            </EmptyDataTemplate>
            
            <ItemTemplate>
                <tr>
                <td><asp:CheckBox ID="CheckBox1" runat="server" Checked="False" Text='' /></td>
                    <td>
                        <asp:Label ID="movie_idLabel" runat="server" Text='<%# Eval("movie_id") %>' />
                    </td>
                    <td>
                        <asp:Label ID="titleLabel" runat="server" Text='<%# Eval("title") %>' />
                    </td>
                    <td>
                        <asp:Label ID="release_dateLabel" runat="server" 
                            Text='<%# Eval("release_date", "{0:d}") %>' />
                    </td>
                </tr>
            </ItemTemplate>
        </asp:ListView>       
            
        <asp:ObjectDataSource runat="server" ID="_moviesDataSource" SelectMethod="GetMovies"
                              TypeName="MsdnMagazine.MoviesDataSource" />    </div>
        <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
        </form>
    </body>
    </html>经初步测试成功本例程序参考了:
    1.The Only Data-binding Control You'll Ever Need
    Fritz Onion    中的ListView.aspx

    2.GridView加入CheckBox实现全选,跨页CheckBox选择
      

  3.   

    对#3楼的代码提一些改进意见:代码写的太多了,实际上可以几乎不写代码而多用清晰的声明性语句。具体来说:1. 我们可以更加直截了当地去判断或者设置某个主键对应的记录是否被选中,而不必在设计时过早考虑ArrayList这种数据结构。例如:bool isDataKeyChecked(string key)
    {
        var x = ViewState[key + "_isChecked"];
        return x == null ? false : (bool)x;
    }void SetDataKeyCheckedValue(string key, bool value)
    {
        ViewState[key + "_isChecked"] = value;
    }2. 在模板中的CheckBox的显示应该使用绑定方式,删除 ItemDataBound 代码。例如:"><asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# isDataKeyChecked((string)Eval("movie_id")) %>' 
        MyDataKey='<% Eval("movie_id")%>' OnCheckedChanged="CheckBox1_CheckedChange" />
    这里每一个CheckBox所在的那一行的主键其实也可以通过CheckBox的NamingContainer属性然后迂回找到,不过既然asp.net没有封装那个方法,我就直截了当地把主键值绑定给自定义属性MyDataKey得啦!3. 当任何一行的CheckBox1的Checked值改变时(即使有多行都被改变了),都会触发CheckedChanged事件,因此每一个CheckBox它自己会主动通知,而不需要“当前页收集选中项的情况”,删除 CollectSelected。例如:protected virtual void CheckBox1_CheckedChange(Object sender, EventArgs args)
    {
        var chk = (CheckBox)sender;
        var key = chk.Attributes["MyDataKey"];
        SetDataKeyCheckedValue(key, chk.Checked);
    }
    即使多条记录的CheckBox被修改,当回发(例如翻页)时每一个CheckBox都会逐一触发事件调用CheckBox_CheckedChange方法,多么简单就能记录全部状态!4. 对于“一页全选”,由于上面的CheckBox1已经可以处理好客户选择操作,所以这可以考虑不回发,而使用javascript来实现。参考:http://topic.csdn.net/u/20090808/17/b2e0cc10-c7bc-4352-bf7a-770f0499de5b.html
    如果要写出易维护的程序,反而要注意少留下执行代码,要重视在设计代码上声明数据绑定。
      

  4.   

    这里核心的就是将“判断一个主键对应的记录有没有被选中”这个功能离散化了,于是代码就简单多了。当你要判断一组主键(跨页的多个记录)有没有被选中过,只要在foreach循环中遍历这些主键调用 isDataKeyChecked 方法来返回对应的行的是否选中状态,而不用管这一行是否在当前页可见。(由于不知道 movie_id是什么类型,我假设是string。如果是其它类型,例如long,那么你需要在调用 isDataKeyChecked 时使用它的 ToString)多用绑定表达式少写代码,也减少了不少代码。特别是由于写查找代码太麻烦,于是我直接在 CheckBox 上放置一个自定义属性 MyDataKey 直接绑定 movie_id。当控件的状态改变,它会自己通知,而不需要你去“收集”。所以删除 CollectSelected,让离散化了的 ChebkBox 直接去调用 SetDataKeyCheckedValue。
      

  5.   

                      ding 。 
      

  6.   

    4. 对于“一页全选”,由于上面的CheckBox1已经可以处理好客户选择操作,所以这可以考虑不回发,而使用javascript来实现。参考:http://topic.csdn.net/u/20090808/17/b2e0cc10-c7bc-4352-bf7a-770f0499de5b.html用javaScript怎么实现? 我昨晚也有看别人在GridView里用了,但ListView里,我写了一下没有成功;
      

  7.   


    很感谢你提的见意,我自己写代码的时候会注意的昨天也是看到博客园的那篇文章<GridView加入CheckBox实现全选,跨页CheckBox选择>,就把他从GridView修改成了ListView,毕竟两控件相差的太大了,很多不能直接用
      

  8.   

    上楼的listview和datapager弄好啦,呵呵,跨页是可以选取,但是获取所有选中的项就不好弄了,使用DataPager后,listView.Items只能获取到当前页的选中的数据项
      

  9.   


    是呀,我也没有好办法,好像用了DataPager后,绑定了项只能是当前页一样
      

  10.   

    你写个js,把选中的行的ID(即你的键)加到一个hiddrenfield里面,用的时候再拿出来