using System; using System.Collections.Generic; using System.Text; using System.Web.UI.WebControls; using System.Web.UI; using System.ComponentModel; using System.Collections; using CommonLib; namespace WebControls { [ToolboxData("<{0}:AXGridView runat=\"server\"></{0}:AXGridView>")] [ParseChildren(true)] [PersistChildren(false)] public class AXGridView : GridView { public AXGridView() : base() { PreRender += new EventHandler(AXGridView_PreRender); try { this.PageSize = SystemConfig.GridViewPageSize; } catch { this.PageSize = 30; } } #region Check Box All Properties private CascadeCheckBoxCollection _cascadeCheckBoxes; [ PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Description("复选框组集合 一个组由一个 全选复选框 和多个 项复选框组成"), Category("扩展") ] public CascadeCheckBoxCollection CascadeCheckBoxes { get { if (_cascadeCheckBoxes == null) { _cascadeCheckBoxes = new CascadeCheckBoxCollection(); } return _cascadeCheckBoxes; } set { _cascadeCheckBoxes = value; } } #endregion #region Check Box All Fields /// <summary> /// 用于存每组的全选复选框ID /// </summary> private string _checkAllIDString; /// <summary> /// 用于存每的项复选框ID /// </summary> private string _checkItemIDString; /// <summary> /// 每行有一个组的所有项复选框 /// </summary> private Dictionary<int, string> _checkItemIDDictionary = new Dictionary<int, string>(); #endregion void AXGridView_PreRender(object sender, EventArgs e) { if (CascadeCheckBoxes.Count > 0) { if (!Page.ClientScript.IsClientScriptBlockRegistered("JsCheckAll")) { Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "JsCheckAll", jsCheckAll); } StringBuilder script = new StringBuilder(); foreach (CascadeCheckbox cc in this.CascadeCheckBoxes) { script.AppendFormat(String.Format("yy_sgv_ccGridView_pre.push('{0}');", this.NamingContainer.Parent == null ? this.ID : string.Format("{0}_{1}", this.NamingContainer.ClientID, this.ID))); script.AppendFormat(String.Format("yy_sgv_ccAll_post.push('{0}');", cc.ParentCheckboxID)); script.AppendFormat(String.Format("yy_sgv_ccItem_post.push('{0}');", cc.ChildCheckboxID)); } // 注册向数组中添加成员的脚本 if (!Page.ClientScript.IsClientScriptBlockRegistered(String.Format("yy_sgv_cascadeCheckbox_{0}", this.ID))) { Page.ClientScript.RegisterClientScriptBlock(this.GetType(), String.Format("yy_sgv_cascadeCheckbox_{0}", this.ID), script.ToString(), true); } } } #region Check Box All Script internal const string jsCheckAll = @"<script type=""text/javascript""> //<![CDATA[ /*联动复选框 开始*/ var yy_sgv_ccGridView_pre = new Array(); // cs中动态向其灌数据(GridView内控件ID的前缀数组) var yy_sgv_ccAll_post = new Array(); // cs中动态向其灌数据(全选复选框ID的后缀数组) var yy_sgv_ccItem_post = new Array(); // cs中动态向其灌数据(项复选框ID的后缀数组) function yy_sgv_ccCheck(e) { /// <summary>单击复选框时</summary> var evt = e || window.event; // FF || IE var obj = evt.target || evt.srcElement // FF || IE var ccIndex = -1; for (var i=0; i<yy_sgv_ccGridView_pre.length; i++) { if (obj.id.startsWith(yy_sgv_ccGridView_pre[i]) && (obj.id.endsWith(yy_sgv_ccAll_post[i]) || obj.id.endsWith(yy_sgv_ccItem_post[i]))) { ccIndex = i; break; } } if (ccIndex != -1) { if (obj.id.endsWith(yy_sgv_ccAll_post[i])) { yy_sgv_ccCheckAll(ccIndex, obj.checked); } else if (obj.id.endsWith(yy_sgv_ccItem_post[i])) { yy_sgv_ccCheckItem(ccIndex); } } } function yy_sgv_ccCheckAll(ccIndex, isCheckAll) { /// <summary>设置全选复选框的状态</summary> var elements = document.getElementsByTagName('INPUT'); for (i=0; i< elements.length; i++) { if (elements[i].type == 'checkbox' && elements[i].id.startsWith(yy_sgv_ccGridView_pre[ccIndex]) && elements[i].id.endsWith(yy_sgv_ccItem_post[ccIndex])) { elements[i].checked = isCheckAll; // if (yy_sgv_crClassName != '') // { // yy_sgv_changeCheckedRowCssClass(elements[i], yy_sgv_crClassName, false); // } } } } function yy_sgv_ccCheckItem(ccIndex) { /// <summary>单击项复选框时</summary> var elements = document.getElementsByTagName('INPUT'); var checkedNum = 0; var uncheckedNum = 0; for (i=0; i< elements.length; i++) { if (elements[i].type == 'checkbox' && elements[i].id.startsWith(yy_sgv_ccGridView_pre[ccIndex]) && elements[i].id.endsWith(yy_sgv_ccItem_post[ccIndex])) { if (elements[i].checked) { checkedNum++; } else { uncheckedNum++; } } } if (uncheckedNum == 0) { yy_sgv_ccCheckCheckbox(yy_sgv_ccGridView_pre[ccIndex], yy_sgv_ccAll_post[ccIndex], true) } else { yy_sgv_ccCheckCheckbox(yy_sgv_ccGridView_pre[ccIndex], yy_sgv_ccAll_post[ccIndex], false) } } function yy_sgv_ccCheckCheckbox(pre, post, isCheckAll) { /// <summary>设置项复选框的状态</summary> var elements = document.getElementsByTagName('INPUT'); for (i=0; i< elements.length; i++) { if (elements[i].type == 'checkbox' && elements[i].id.startsWith(pre) && elements[i].id.endsWith(post)) { elements[i].checked = isCheckAll; break; } } } function yy_sgv_ccListener() { /// <summary>监听所有联动复选框的单击事件</summary> var elements = document.getElementsByTagName('INPUT'); for (i=0; i< elements.length; i++) { if (elements[i].type == 'checkbox') { for (j=0; j<yy_sgv_ccGridView_pre.length; j++) { if (elements[i].id.startsWith(yy_sgv_ccGridView_pre[j]) && (elements[i].id.endsWith(yy_sgv_ccAll_post[j]) || elements[i].id.endsWith(yy_sgv_ccItem_post[j]))) { //alert(elements[i].id +' '+ yy_sgv_ccGridView_pre[j]+' ' + yy_sgv_ccAll_post[j] +' '+yy_sgv_ccItem_post[j] ); Fun_addEvent(elements[i], 'click', yy_sgv_ccCheck); break; } } } } } if (document.all) { window.attachEvent('onload', yy_sgv_ccListener) } else { window.addEventListener('load', yy_sgv_ccListener, false); } //]]> </script>"; #endregion #region Empty Row public string EmptyTableClientID { get { if (ViewState["EmptyTableClientID"] == null) { return string.Empty; } return ViewState["EmptyTableClientID"].ToString(); } set { ViewState["EmptyTableClientID"] = value; } } public bool DisplayEmptyRow { get { if (ViewState["DisplayEmptyRow"] == null) { return true; } return Convert.ToBoolean(ViewState["DisplayEmptyRow"]); } set { ViewState["DisplayEmptyRow"] = value; } } public bool DisplayEmptyText { get { if (ViewState["DisplayEmptyText"] == null) { return true; } return Convert.ToBoolean(ViewState["DisplayEmptyText"]); } set { ViewState["DisplayEmptyText"] = value; } } public string EmptyRowText { get { if (ViewState["EmptyRowText"] == null) { return ""; } return ViewState["EmptyRowText"].ToString(); } set { ViewState["EmptyRowText"] = value; } } /// <summary> /// Display empty row if no row return from data source /// </summary> /// <param name="e"></param> protected override void OnDataBound(EventArgs e) { base.OnDataBound(e); if (this.Rows.Count == 0 && DisplayEmptyRow) { int visibleColumnCount = 0; GridViewRow newRow = new GridViewRow(0, 0, DataControlRowType.DataRow, DataControlRowState.Normal); for (int i = 0; i < this.Columns.Count; i++) { if (this.Columns[i].Visible) { //TODO: set up empty row style here TableHeaderCell cell = new TableHeaderCell(); cell.Text = this.Columns[i].HeaderText; cell.Scope = TableHeaderScope.Column; //cell.BackColor = this.HeaderStyle.BackColor; //cell.ForeColor = this.HeaderStyle.ForeColor; //cell.Font.CopyFrom(this.HeaderStyle.Font); //cell.Font.Bold = true; //cell.VerticalAlign = this.HeaderStyle.VerticalAlign; newRow.Cells.Add(cell); visibleColumnCount++; } } newRow.BackColor = HeaderStyle.BackColor; newRow.ForeColor = HeaderStyle.ForeColor; newRow.Font.CopyFrom(HeaderStyle.Font); newRow.VerticalAlign = HeaderStyle.VerticalAlign; newRow.HorizontalAlign = HeaderStyle.HorizontalAlign; newRow.CssClass = HeaderStyle.CssClass; newRow.BorderStyle = HeaderStyle.BorderStyle; newRow.BorderWidth = HeaderStyle.BorderWidth; newRow.Height = HeaderStyle.Height; newRow.Width = HeaderStyle.Width; Table table = new Table(); table.CopyBaseAttributes(this); table.ID = "Table"; table.Rows.Add(newRow); if (DisplayEmptyText) { GridViewRow newRow2 = new GridViewRow(0, 0, DataControlRowType.DataRow, DataControlRowState.Normal); newRow2.Cells.Add(new TableCell()); newRow2.Cells[0].Text = EmptyRowText; newRow2.Cells[0].BackColor = this.Columns[0].ItemStyle.BackColor; newRow2.Cells[0].ForeColor = this.Columns[0].ItemStyle.ForeColor; newRow2.Cells[0].ColumnSpan = visibleColumnCount; newRow2.Cells[0].HorizontalAlign = HorizontalAlign.Center; table.Rows.Add(newRow2); } table.Style[HtmlTextWriterStyle.Height] = "auto;"; this.Controls.Add(table); EmptyTableClientID = table.ClientID; } else { EmptyTableClientID = this.ClientID; } } #endregion #region Sort Tooltip //private SortTip _sortTip; /// <summary> /// Sort tooltip information /// </summary> //[Description("Sort tooltip information"), //Category("Expand"), //DesignerSerializationVisibility(DesignerSerializationVisibility.Content), //PersistenceMode(PersistenceMode.InnerProperty)] //public virtual SortTip SortTip //{ // get // { // if (_sortTip == null) // { // _sortTip = new SortTip(); // } // return _sortTip; // } //} #endregion #region Command Buttons Confirm Message public string SelectConfirmMessage { get { if (ViewState["SelectConfirmMessage"] == null) { return string.Empty; } return ViewState["SelectConfirmMessage"].ToString(); } set { ViewState["SelectConfirmMessage"] = value; } } public string DeleteConfirmMessage { get { if (ViewState["DeleteConfirmMessage"] == null) { return ""; } return ViewState["DeleteConfirmMessage"].ToString(); } set { ViewState["DeleteConfirmMessage"] = value; } } public string DeleteSelectedConfirmMessage { get { if (ViewState["DeleteSelectedConfirmMessage"] == null) { return ""; } return ViewState["DeleteSelectedConfirmMessage"].ToString(); } set { ViewState["DeleteSelectedConfirmMessage"] = value; } } public string UpdateConfirmMessage { get { if (ViewState["UpdateConfirmMessage"] == null) { return string.Empty; } return ViewState["UpdateConfirmMessage"].ToString(); } set { ViewState["UpdateConfirmMessage"] = value; } } public string EditConfirmMessage { get { if (ViewState["EditConfirmMessage"] == null) { return string.Empty; } return ViewState["EditConfirmMessage"].ToString(); } set { ViewState["EditConfirmMessage"] = value; } } public string CancelConfirmMessage { get { if (ViewState["CancelConfirmMessage"] == null) { return string.Empty; } return ViewState["CancelConfirmMessage"].ToString(); } set { ViewState["CancelConfirmMessage"] = value; } } #endregion #region Sort Image And Text private string _sortDescImage = "../App_Themes/Default/Images/desc.gif"; /// <summary> /// 降序提示图片 /// </summary> public string SortDescImage { get { return _sortDescImage; } set { _sortDescImage = value; } } private string _sortAscImage = "../App_Themes/Default/Images/asc.gif"; /// <summary> /// 升序提示图片 /// </summary> public string SortAscImage { get { return _sortAscImage; } set { _sortAscImage = value; } } private string _sortDescText; /// <summary> /// 降序提示文本 /// </summary> public string SortDescText { get { return _sortDescText; } set { _sortDescText = value; } } private string _sortAscText; /// <summary> /// 升序提示文本 /// </summary> public string SortAscText { get { return _sortAscText; } set { _sortAscText = value; } } #endregion protected override void OnRowDataBound(GridViewRowEventArgs e) { #region Sort Tooltip if (e.Row.RowType == DataControlRowType.Header) { for (int i = 0; i < e.Row.Cells.Count; i++) { LinkButton lbtn = null; if (e.Row.Cells[i].Controls.Count > 0) { for (int k = 0; k < e.Row.Cells[i].Controls.Count; k++) { lbtn = e.Row.Cells[i].Controls[k] as LinkButton; if (lbtn != null) { if (lbtn.CommandArgument.Equals(this.SortExpression)) { Image imgControl = null; Label lblControl = null; //Ascending sort if (this.SortDirection == SortDirection.Ascending) { //if (!string.IsNullOrEmpty(this.SortTip.SortAscText)) //{ // lblControl = new Label(); // lblControl.Text = this.SortTip.SortAscText; //} //if (!string.IsNullOrEmpty(this.SortTip.SortAscImage)) //{ // imgControl = new Image(); // imgControl.ImageUrl = ResolveUrl(this.SortTip.SortAscImage); //} if (!string.IsNullOrEmpty(this.SortAscText)) { lblControl = new Label(); lblControl.Text = this.SortAscText; } if (!string.IsNullOrEmpty(this.SortAscImage)) { imgControl = new Image(); imgControl.ImageUrl = ResolveUrl(this.SortAscImage); } } else { //if (!string.IsNullOrEmpty(this.SortTip.SortDescText)) //{ // lblControl = new Label(); // lblControl.Text = this.SortTip.SortDescText; //} //if (!string.IsNullOrEmpty(this.SortTip.SortDescImage)) //{ // imgControl = new Image(); // imgControl.ImageUrl = ResolveUrl(this.SortTip.SortDescImage); //} if (!string.IsNullOrEmpty(this.SortDescText)) { lblControl = new Label(); lblControl.Text = this.SortDescText; } if (!string.IsNullOrEmpty(this.SortDescImage)) { imgControl = new Image(); imgControl.ImageUrl = ResolveUrl(this.SortDescImage); } } //Add sort tooltip text and image to sort field if (lblControl != null) { e.Row.Cells[i].Controls.Add(lblControl); } if (imgControl != null) { e.Row.Cells[i].Controls.Add(imgControl); } } } } } } } #endregion #region Command Buttons Confirm Message if (e.Row.RowType == DataControlRowType.DataRow) { foreach (TableCell tc in e.Row.Cells) { foreach (Control ctl in tc.Controls) { if (ctl is IButtonControl) { IButtonControl cmdButton = ctl as IButtonControl; if (!string.IsNullOrEmpty(DeleteConfirmMessage) && cmdButton.CommandName.ToLower() == "delete") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", DeleteConfirmMessage)); } if (!string.IsNullOrEmpty(SelectConfirmMessage) && cmdButton.CommandName.ToLower() == "select") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", SelectConfirmMessage)); } if (!string.IsNullOrEmpty(EditConfirmMessage) && cmdButton.CommandName.ToLower() == "edit") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", EditConfirmMessage)); } if (!string.IsNullOrEmpty(UpdateConfirmMessage) && cmdButton.CommandName.ToLower() == "update") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", UpdateConfirmMessage)); } if (!string.IsNullOrEmpty(CancelConfirmMessage) && cmdButton.CommandName.ToLower() == "cancel") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", CancelConfirmMessage)); } } } } } if (e.Row.RowType == DataControlRowType.Header) { foreach (TableCell tc in e.Row.Cells) { foreach (Control ctl in tc.Controls) { if (ctl is IButtonControl) { IButtonControl cmdButton = ctl as IButtonControl; if (!string.IsNullOrEmpty(DeleteSelectedConfirmMessage) && cmdButton.CommandName.ToLower() == "deleteselected") { IAttributeAccessor iattr = (IAttributeAccessor)cmdButton; iattr.SetAttribute("onclick", string.Format("javascript:return confirm('{0}');", DeleteSelectedConfirmMessage)); } } } } } #endregion #region Check Box All if (e.Row.RowType == DataControlRowType.DataRow) { //for (int i = 0; i < e.Row.Cells.Count; i++) //{ // for (int j = 0; j < e.Row.Cells[i].Controls.Count; j++) // { // if (e.Row.Cells[i].Controls[j] is CheckBox) // { // CheckBox chk = e.Row.Cells[i].Controls[j] as CheckBox; // bool isCheckBoxAll = false; // foreach (CheckboxAll cba in this.CheckBoxAlls) // { // if (chk.NamingContainer.ClientID + "_" + cba.CheckboxItemID == chk.ClientID) // { // isCheckBoxAll = true; // break; // } // } // if (isCheckBoxAll) // { // chk.Attributes.Add("onclick", "yy_ClickCheckItem()"); // if (_checkItemIDDictionary.Count == 0 || !_checkItemIDDictionary.ContainsKey(i)) // { // _checkItemIDDictionary.Add(i, chk.ClientID); // } // else // { // string s; // _checkItemIDDictionary.TryGetValue(i, out s); // _checkItemIDDictionary.Remove(i); // _checkItemIDDictionary.Add(i, s + this.ItemSeparator + chk.ClientID); // } // break; // } // } // } //} } else if (e.Row.RowType == DataControlRowType.Header) { //for (int i = 0; i < e.Row.Cells.Count; i++) //{ // for (int j = 0; j < e.Row.Cells[i].Controls.Count; j++) // { // if (e.Row.Cells[i].Controls[j] is CheckBox) // { // CheckBox chk = (CheckBox)e.Row.Cells[i].Controls[j]; // bool isCheckboxAll = false; // foreach (CheckboxAll cba in this.CheckBoxAlls) // { // if (chk.NamingContainer.ClientID + "_" + cba.CheckboxAllID == chk.ClientID) // { // isCheckboxAll = true; // break; // } // } // if (isCheckboxAll) // { // chk.Attributes.Add("onclick", "yy_ClickCheckAll(this)"); // if (String.IsNullOrEmpty(this._checkAllIDString)) // { // this._checkAllIDString += chk.ClientID; // } // else // { // this._checkAllIDString += this.GroupSeparator + chk.ClientID; // } // break; // } // } // } //} } else if (e.Row.RowType == DataControlRowType.Pager) { //TODO: //LinkButton lbtnDelete = new LinkButton(); //lbtnDelete.Text = "Delete Selected"; //lbtnDelete.CommandName = "deleteall"; //e.Row.Cells[0].Controls.Add(lbtnDelete); } #endregion base.OnRowDataBound(e); } /// <summary> /// 获取GridView中通过复选框选中的行的DataKey集合 /// </summary> /// <param name="columnIndex">CheckBox在GridView中的列索引</param> /// <returns></returns> public List<DataKey> GetCheckedDataKey(int columnIndex) { if (this.DataKeyNames.Length == 0) throw new ArgumentNullException("DataKeys", "DataKeyNames are null or empty."); List<DataKey> list = new List<DataKey>(); int i = 0; foreach (GridViewRow row in this.Rows) { if (row.RowType == DataControlRowType.DataRow) { foreach (Control c in row.Cells[columnIndex].Controls) { if (c is CheckBox && ((CheckBox)c).Checked) { list.Add(this.DataKeys[i]); break; } } i++; } } return list; } /// <summary> /// 获取GridView中通过复选框选中的行的DataKey集合 /// </summary> /// <param name="columnIndex">CheckBox在GridView中的列索引</param> /// <param name="columnIndex">Whether the checkbox was selected</param> /// <returns></returns> public string BuildXmlStringByDataKey(string xmlRootName, int columnIndex, out bool isCheck) { if (this.DataKeyNames.Length == 0) throw new ArgumentNullException("DataKeys", "DataKeyNames are null or empty."); StringBuilder xmlString = new StringBuilder(); xmlString.AppendFormat("<{0}>", xmlRootName); isCheck = false; int i = 0; foreach (GridViewRow row in this.Rows) { if (row.RowType == DataControlRowType.DataRow) { foreach (Control c in row.Cells[columnIndex].Controls) { if (c is CheckBox && ((CheckBox)c).Checked) { xmlString.AppendFormat("<value>{0}</value>", this.DataKeys[i].Value); isCheck = true; break; } } i++; } } xmlString.AppendFormat("</{0}>", xmlRootName); return xmlString.ToString(); } } /// <summary> /// Sort tip helper class /// </summary> [TypeConverter(typeof(ExpandableObjectConverter))] public class SortTip { private string _sortDescImage; /// <summary> /// 降序提示图片 /// </summary> [ Description("降序提示图片"), Category("扩展"), Editor("System.Web.UI.Design.UrlEditor", typeof(System.Drawing.Design.UITypeEditor)), DefaultValue(""), NotifyParentProperty(true) ] public string SortDescImage { get { return _sortDescImage; } set { _sortDescImage = value; } } private string _sortAscImage; /// <summary> /// 升序提示图片 /// </summary> [ Description("升序提示图片"), Category("扩展"), Editor("System.Web.UI.Design.UrlEditor", typeof(System.Drawing.Design.UITypeEditor)), DefaultValue(""), NotifyParentProperty(true) ] public string SortAscImage { get { return _sortAscImage; } set { _sortAscImage = value; } } private string _sortDescText; /// <summary> /// 降序提示文本 /// </summary> [ Description("降序提示文本"), Category("扩展"), DefaultValue(""), NotifyParentProperty(true) ] public string SortDescText { get { return _sortDescText; } set { _sortDescText = value; } } private string _sortAscText; /// <summary> /// 升序提示文本 /// </summary> [ Description("升序提示文本"), Category("扩展"), DefaultValue(""), NotifyParentProperty(true) ] public string SortAscText { get { return _sortAscText; } set { _sortAscText = value; } } /// <summary> /// ToString() /// </summary> /// <returns></returns> public override string ToString() { return "SortTip"; } } /// <summary> /// CheckboxAll class for multi-selection support /// </summary> [ToolboxItem(false)] public class CascadeCheckbox { private string _ParentCheckboxID; /// <summary> /// Parent box ID in template /// </summary> public string ParentCheckboxID { set {_ParentCheckboxID= value;} get { return _ParentCheckboxID; } } private string _ChildCheckboxID; /// <summary> /// Child item box ID in template /// </summary> public string ChildCheckboxID { set { _ChildCheckboxID = value; } get { return _ChildCheckboxID; } } } public class CascadeCheckBoxCollection : CollectionBase { public CascadeCheckBoxCollection() : base() { } public CascadeCheckbox this[int index] { get { return base.List[index] as CascadeCheckbox; } set { base.List[index] = (CascadeCheckbox)value; } } public void Add(CascadeCheckbox item) { base.List.Add(item); } public void Remove(int index) { if (index > -1 && index < base.Count) { base.List.RemoveAt(index); } } public override string ToString() { return "CascadeCheckBoxCollection"; } } }