zoukankan      html  css  js  c++  java
  • GridView分页可以全选的改造

    记上次有个项目,有几个都要求在GridView里可以进行对应的多选操作.本来这问题没什么难度,加上要求分页后就有点烦人了,因时间紧,想的最简单的方法就是用Session保存每页选择结果,现项目告一段落,静下来想了下,扩展GridView可以全选操作,用ViewState来保存(?不是吧,用ViewState,你不怕整个机器都读一个页面死机啊)所以这边会保证ViewState肯定记录没有很多内容.先看代码,比较简单.
          public class TGridView : GridView
        {
            #region 可以进行多项选择
    
            #region 对应选择的项目
    
            #region "全选在那列"
            [Browsable(true)]
            [DefaultValue(0)]
            public int CheckBoxIndex
            {
                get
                {
                    object obj = this.ViewState["CheckBoxIndex"];
                    if (obj != null)
                    {
                        return (int)obj;
                    }
                    return 0;
                }
                set
                {
                    if (value < 0)
                    {
                        throw new ArgumentOutOfRangeException("value");
                    }
                    this.ViewState["CheckBoxIndex"] = value;
                }
            }
            #endregion
    
            #region 是否添加选择栏位
            [Browsable(true)]
            [DefaultValue(false)]
            public bool AddCheckBox
            {
                get;
                set;
            }
            #endregion
    
            /// <summary>
            /// 全选是否
            /// </summary>
            public bool? AllSelect
            {
                get
                {
                    object obj = this.ViewState["AllSelect"];
                    if (obj != null)
                    {
                        return (bool)obj;
                    }
                    return null;
                }
                set
                {
                    object obj = this.ViewState["AllSelect"];
                    if (value != null)
                    {
                        this.ViewState["AllSelect"] = value;
                    }
                    else
                    {
                        this.ViewState["AllSelect"] = null;
                    }
                }
            }
    
            /// <summary>
            /// 记录对应的主键信息(没全选时记录选上的,全选后记录没被选上的)
            /// </summary>
            public string MarkerID
            {
                get
                {
                    object obj = this.ViewState["MarkerID"];
                    return obj == null ? string.Empty : (string)obj;
                }
                private set
                {
                    if (!object.Equals(value, this.ViewState["MarkerID"]))
                    {
                        this.ViewState["MarkerID"] = value;
                    }
                }
            }
    
            #endregion
    
            #region 初始化信息
            /// <summary>
            /// 创建一列为CheckBox的栏位
            /// </summary>
            /// <param name="dataSource"></param>
            /// <param name="useDataSource"></param>
            /// <returns></returns>
            protected override ICollection CreateColumns(PagedDataSource dataSource, bool useDataSource)
            {
                ArrayList list = base.CreateColumns(dataSource, useDataSource) as ArrayList;
                if (AddCheckBox)
                {
                    SelectDataField select = new SelectDataField();
                    select.CheckboxChanged += new SelectDataField.CheckboxChangedEventHandler(select_CheckboxChanged);
                    list.Insert(CheckBoxIndex, select);
                }
                return list;
            }
    
            /// <summary>
            /// 当全选后先清空前面记录的主键信息,然后更新对应CheckBox的值
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void select_CheckboxChanged(object sender, EventArgs e)
            {
                CheckBox box = sender as CheckBox;
                AllSelect = box.Checked;
                MarkerID = string.Empty;
                UpdateGridViewSelect();
            }
            #endregion
    
            #region 保持页面CheckBox的状态
            /// <summary>
            /// 每次分页操作前执行或收集对应结果的CheckBox的值调用
            /// </summary>
            public void CheckGridViewSelect()
            {
                if (DataKeyNames.Length < 1)
                    throw new Exception("GridView没有设置DataKeyNames");
                string markids = MarkerID;
                foreach (GridViewRow row in this.Rows)
                {
                    CheckBox box = row.Cells[CheckBoxIndex].Controls[0] as CheckBox;
                    if (box != null)
                    {
                        string key = this.DataKeys[row.RowIndex].Value.ToString() + ";";
                        bool allSelect = AllSelect ?? false;
                        if (box.Checked != allSelect && !markids.Contains(key))
                        {
                            markids += key;
                        }
                        else if (box.Checked == allSelect && markids.Contains(key))
                        {
                            markids.Replace(key, "");
                        }
                    }
                }
                MarkerID = markids;
            }
            /// <summary>
            /// 每次重新绑定时把相应的CheckBox赋上值
            /// </summary>
            private void UpdateGridViewSelect()
            {
                if (this.DataKeyNames.Length < 1)
                    throw new Exception("GridView没有设置DataKeyNames");
                UpdateGridViewHeadSelect();
                string markids = MarkerID;
                foreach (GridViewRow row in this.Rows)
                {
                    CheckBox box = row.Cells[CheckBoxIndex].Controls[0] as CheckBox;
                    if (box != null)
                    {
                        string key = this.DataKeys[row.RowIndex].Value.ToString() + ";";
                        bool bMarkid = markids.Contains(key);
                        bool allSelect = AllSelect ?? false;
                        box.Checked = bMarkid != allSelect;
                    }
                }
            }
            /// <summary>
            /// 更新GridView栏位上的CheckBox
            /// </summary>
            private void UpdateGridViewHeadSelect()
            {
                if (this.HeaderRow != null)
                {
                    CheckBox box = this.HeaderRow.Cells[CheckBoxIndex].Controls[0] as CheckBox;
                    if (box != null)
                        box.Checked = AllSelect ?? false;
                }
            }
            /// <summary>
            /// 分页时调用修改的CheckBox值.
            /// </summary>
            /// <param name="e"></param>
            protected override void OnPageIndexChanging(GridViewPageEventArgs e)
            {
                if (AddCheckBox)
                    CheckGridViewSelect();
                base.OnPageIndexChanging(e);
            }
            /// <summary>
            /// 分页完成后给CheckBox赋值
            /// </summary>
            /// <param name="e"></param>
            protected override void OnPageIndexChanged(EventArgs e)
            {
                if (AddCheckBox)
                    UpdateGridViewSelect();
                base.OnPageIndexChanged(e);
            }
            protected override void OnRowDataBound(GridViewRowEventArgs e)
            {   
                if (AddCheckBox)
                    UpdateGridViewSelect();           
                base.OnDataBound(e);
            }        #endregion
    
            #region 供后台得到选择了的主键信息,或检测主键是否选择了的对应函数
            /// <summary>
            /// 得到被标记的主键,如果是全选状态,刚是得到没被勾选的主键集,反之是得到被勾选的主键集
            /// </summary>
            /// <typeparam name="T">主键类型</typeparam>
            /// <param name="bSelect">得到全选状态</param>
            /// <returns></returns>
            public List<T> GetSelectKey<T>(out bool bSelect)
            {
                CheckGridViewSelect();
                bSelect = AllSelect ?? false;
                string markids = MarkerID;
                if (string.IsNullOrEmpty(markids))
                    return new List<T>();
                markids = markids.TrimEnd(';');
                return markids.Split(';').ToList()
                        .Select(p => StringConvertT<T>(p))
                        .ToList();
            }
            /// <summary>
            /// 查找GridView里选择了的数据
            /// </summary>
            /// <typeparam name="T">数据源的每条数据类型</typeparam>
            /// <param name="data">GridView的数据源</param>        
            /// <returns></returns>
            public List<T> GetSelectData<T>(IEnumerable<T> data)
            {
                return GetSelectData<T>(data, true);
            }
            /// <summary>
            /// 查找GridView里是否选择了的数据
            /// </summary>
            /// <typeparam name="T">数据源的每条数据类型</typeparam>
            /// <param name="data">GridView的数据源</param>
            /// <param name="IsSelect">true表示查找勾选上的,false表示查找没被勾选上的</param>
            /// <returns></returns>
            public List<T> GetSelectData<T>(IEnumerable<T> data, bool bSelect)
            {
                CheckGridViewSelect();
                bool allSelect = AllSelect ?? false;
                string markids = MarkerID;
                PropertyInfo info = typeof(T).GetProperty(DataKeyNames[0]);
                if (info == null)
                    throw new Exception("请确认数据源里有属性" + DataKeyNames[0] + ".");
                var result = data.Where(p =>
                {
                    var id = info.GetValue(p, null).ToString();
                    if (bSelect)
                        return allSelect != markids.Contains(id + ";");
                    else
                        return allSelect == markids.Contains(id + ";");
                });
                return result.ToList();
            }
            /// <summary>
            /// 查看一行的主键是否被选中(要保证传入的key是在数据源里的,不然全选状态下可能会得到错误结果.)
            /// </summary>
            /// <param name="key">主键</param>
            /// <returns>true-选中,false-没被选择</returns>
            public bool IsSelect(object key)
            {
                CheckGridViewSelect();
                bool allSelect = AllSelect ?? false;
                return allSelect != MarkerID.Contains(key.ToString() + ";");
            }
            /// <summary>
            /// 把string类数据转化成对应的T,支持基本数据
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="data"></param>
            /// <returns></returns>
            private T StringConvertT<T>(string data)
            {
                if (string.IsNullOrEmpty(data))
                    throw new NullReferenceException("主建不能用空.");
                if (typeof(T) == typeof(Guid))
                {
                    object id = new Guid(data);
                    return (T)id;
                }
                else if (typeof(T).IsAssignableFrom(typeof(IConvertible)))
                {
                    object t = Convert.ChangeType(data, typeof(T));
                    return (T)t;
                }
                else
                {
                    throw new Exception("不支持的类型.");
                }
            }
            #endregion
    
            #endregion
        }
        public class SelectDataField : DataControlField
        {
            private CheckBox box;
    
            public SelectDataField()
            {
                box = new CheckBox();
            }
    
            protected override DataControlField CreateField()
            {
                return new SelectDataField();
            }
    
            public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
            {
                base.InitializeCell(cell, cellType, rowState, rowIndex);
                switch (cellType)
                {
                    case DataControlCellType.Header:
                        {
                            box.CheckedChanged += new EventHandler(box_CheckedChanged);
                            box.Text = "选择";
                            box.TextAlign = TextAlign.Right;
                            box.AutoPostBack = true;
                            cell.HorizontalAlign = HorizontalAlign.Left;
                            cell.Controls.Add(box);
                            break;
                        }
                    case DataControlCellType.DataCell:
                        {
                            CheckBox checkbox = new CheckBox();
                            checkbox.AutoPostBack = false;
                            cell.Controls.Add(checkbox);
                            break;
                        }
                    default:
                        break;
                }
            }
            public delegate void CheckboxChangedEventHandler(object sender, EventArgs e);
            public event CheckboxChangedEventHandler CheckboxChanged;
    
            void box_CheckedChanged(object sender, EventArgs e)
            {
                if (CheckboxChanged != null)
                    CheckboxChanged(sender, e);
            }
        }

    这里还是说下怎么记录各个选择项的,就我使用全选操作后的条目.

    1.没有点击全选,那么我用MarkerID记录所有选择了的主键.

    2.点击全选后,那么我用MarkerID记录的是所有去掉选择了的主键. 每次点击全选,都用清空MarkerID.还有,TGridView一定要设置DataKeyNames. 下用是效果图.

    从上面也可以看出, DataKeyNames.Length应该只能为1,就是说不设置或设置几个是有问题的,其实这个大家有兴趣,可以自己修改相关的一些代码.

            <asp:TGridView ID="grvViewT" AutoGenerateColumns="false" CheckBoxIndex="2" runat="server" AllowPaging="true" OnPageIndexChanging="grvViewT_PageIndexChanging"
              DataKeyNames="ID" >
                <Columns>
                    <asp:BoundField DataField="A" HeaderText="A" />
                    <asp:BoundField DataField="B" HeaderText="B" />
                    <asp:BoundField DataField="C" HeaderText="C" />
                    <asp:BoundField DataField="D" HeaderText="D" />
                </Columns>
            </asp:TGridView>

    相关资料:

    http://www.cnblogs.com/yanyangtian/category/155681.html

    还有相关Reflector的相关GridView的源码.

  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/zhouxin/p/1979880.html
Copyright © 2011-2022 走看看