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的源码.

  • 相关阅读:
    应用量化时代 | 微服务架构的服务治理之路
    API网关——Kong实践分享
    容器云未来:Kubernetes、Istio 和 Knative
    微服务网关实战——Spring Cloud Gateway
    服务迁移之路 | Spring Cloud向Service Mesh转变
    基于事件驱动机制,在Service Mesh中进行消息传递的探讨
    MSMQ 和 MQTT
    MQTT和WebSocket
    NetCore WebSocket 即时通讯示例
    .NET 即时通信,WebSocket服务端实例
  • 原文地址:https://www.cnblogs.com/zhouxin/p/1979880.html
Copyright © 2011-2022 走看看