在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Web.UI.Design.WebControls; using System.Text; using System.Drawing; [assembly:TagPrefix("Microsoft.Gtec.Dsv", "gtecdsv")] namespace Microsoft.Gtec.Dsv { /// <summary> /// Summary description for WebCustomControl1. /// </summary> [ToolboxData("<{0}:ScrollableFixedHeaderDataGrid runat=server></{0}:ScrollableFixedHeaderDataGrid>")] public class ScrollableFixedHeaderDataGrid: System.Web.UI.WebControls.DataGrid { protected override void Render(HtmlTextWriter output) { //Use this flag to determine whether the component is in design-time or runtime. //The control will be rendered differently in IDE. //Don't bother to use DataGridDesigner.GetDesignTimeHtml bool designMode = ((Site != null) && (Site.DesignMode)); //Backing up the properties need to change during the render process string tempLeft = Style["LEFT"]; string tempTop = Style["TOP"]; Unit tempHeight = Height; string tempTableStyle = Style["TABLE-LAYOUT"]; //Render a "<div>" container with scrollbars. output.WriteBeginTag("div"); output.WriteAttribute("id",ID + "_div"); output.WriteAttribute("style", "HEIGHT: " + Height + ";" + //Leave 20px for the vertical scroll bar, //assuming the end-user will not set his scroll bar to more than 20px. "WIDTH: " + (Width.Value + 20) + "px;" + "TOP: " + Style["TOP"] + ";" + "LEFT: " + Style["LEFT"] + ";" + "POSITION: " + Style["POSITION"] + ";" + "OVERFLOW-X: auto;" + "Z-INDEX: " + Style["Z-INDEX"] + ";" + //Render the scrollbar differently for design-time and runtime. "OVERFLOW-Y: " + (designMode?"scroll":"auto") ); output.Write(HtmlTextWriter.TagRightChar); //The DataGrid is inside the "<div>" element, so place it at (0,0). Style["LEFT"] = "0px"; Style["TOP"] = "0px"; //Render the DataGrid. base.Render(output); output.WriteEndTag("div"); //Restore the values Style["LEFT"] = tempLeft; Style["TOP"] = tempTop; //The following rendering is only necessary under runtime. It has negative impact during design time. if (!designMode) { //Render another copy of the DataGrid with only headers. //Render it after the DataGrid with contents, //so that it is on the top. Z-INDEX is more complex here. //Set Height to 0, so that it will adjust on its own. Height = new Unit("0px"); StringWriter sw = new StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(sw); //This style is important for matching column widths later. Style["TABLE-LAYOUT"] = "fixed"; base.Render(htw); StringBuilder sbRenderedTable = sw.GetStringBuilder(); htw.Close(); sw.Close(); Debug.Assert((sbRenderedTable.Length > 0), "Rendered HTML string is empty. Check viewstate usage and databinding."); string temp = sbRenderedTable.ToString(); if (sbRenderedTable.Length > 0) { //AllowPaging at the top? if ((AllowPaging) && ((PagerPosition.Top == PagerStyle.Position || (PagerPosition.TopAndBottom == PagerStyle.Position)))) { Trace.WriteLine(temp); sbRenderedTable.Replace(ID,ID + "_Pager", 0, (temp.IndexOf(ID) + ID.Length)); temp = sbRenderedTable.ToString(); string pager = temp.Substring(0, temp.ToLower().IndexOf(@"</tr>") + 5); Trace.WriteLine(pager); output.Write(pager); output.WriteEndTag("table"); //Start of pager's <tr> int start = temp.ToLower().IndexOf(@"<tr"); //End of pager's </tr> int end = temp.ToLower().IndexOf(@"</tr>") + 5; //Remove the <tr> for pager from the string. Prepare to render the headers. sbRenderedTable.Remove(start,end-start); Trace.WriteLine(sbRenderedTable.ToString()); sbRenderedTable.Replace(ID + "_Pager",ID + "_Headers", 0, (temp.IndexOf(ID+"_Pager") + (ID+"_Pager").Length)); temp = sbRenderedTable.ToString(); string tableHeaders = temp.Substring(0, (temp.ToLower()).IndexOf(@"</tr>") + 5); Trace.WriteLine(tableHeaders); output.Write(tableHeaders); output.WriteEndTag("table"); string headerID = ID + "_Headers"; string pagerID = ID + "_Pager"; string divID = ID + "_div"; string adjustWidthScript = @" <script language=javascript> //debugger; var headerTableRow = " + headerID + @".rows[0]; var originalTableRow = " + ID + @".rows[1];" //Adjust header row's height. + @" headerTableRow.height = originalTableRow.offsetHeight; " + //Adjust pager row's height, width. pagerID + @".rows[0].height = " + ID + @".rows[0].offsetHeight; " + pagerID + @".style.width = " + ID + @".offsetWidth; for (var i = 0; i < headerTableRow.cells.length; i++) { headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth; } " + //Also needs to adjust the width of the "<div>" at client side in addition to servier side, //since the Table's actual width can go beyond the width specified at server side under Edit mode. //The server side width manipulation is mainly for design-time appearance. divID + @".style.width = " + ID + @".offsetWidth + 20 + 'px'; " + //The following script is for flow-layout. We cannot get the position of the control //on server side if the the page is with flow-layout. headerID + @".style.left = " + divID + @".offsetLeft; " + headerID + @".style.top = " + divID + @".offsetTop + " + pagerID + @".offsetHeight; " + headerID + @".style.position = 'absolute'; " + pagerID + @".style.left = " + divID + @".offsetLeft; " + pagerID + @".style.top = " + divID + @".offsetTop; " + pagerID + @".style.position = 'absolute'; </script>"; Page.RegisterStartupScript("dummyKey" + this.ID, adjustWidthScript); //output.Write(adjustWidthScript); } else { //Replace the table's ID with a new ID. //It is tricky that we must only replace the 1st occurence, //since the rest occurences can be used for postback scripts for sorting. sbRenderedTable.Replace(ID,ID + "_Headers", 0, (temp.IndexOf(ID) + ID.Length)); Trace.WriteLine(sbRenderedTable.ToString()); //We only need the headers, stripping the rest contents. temp = sbRenderedTable.ToString(); string tableHeaders = temp.Substring(0, (temp.ToLower()).IndexOf(@"</tr>") + 5); Trace.WriteLine(tableHeaders); output.Write(tableHeaders); output.WriteEndTag("table"); //Client side script for matching column widths. //Can't find a way to do this on the server side, since the browser can change widths on the client side. string adjustWidthScript = @" <script language=javascript> //debugger; var headerTableRow = " + this.ID + @"_Headers.rows[0]; var originalTableRow = " + this.ID + @".rows[0]; headerTableRow.height = originalTableRow.offsetHeight; for (var i = 0; i < headerTableRow.cells.length; i++) { headerTableRow.cells[i].width = originalTableRow.cells[i].offsetWidth; } " + //Also needs to adjust the width of the "<div>" at client side in addition to servier side, //since the Table's actual width can go beyond the width specified at server side under Edit mode. //The server side width manipulation is mainly for design-time appearance. this.ID + "_div" + @".style.width = " + this.ID + @".offsetWidth + 20 + 'px'; " + //The following script is for flow-layout. We cannot get the position of the control //on server side if the the page is with flow-layout. this.ID + "_Headers" + @".style.left = " + this.ID + @"_div.offsetLeft; " + this.ID + "_Headers" + @".style.top = " + this.ID + @"_div.offsetTop; " + this.ID + "_Headers" + @".style.position = 'absolute'; </script>"; Page.RegisterStartupScript("dummyKey" + this.ID, adjustWidthScript); //output.Write(adjustWidthScript); } Height = tempHeight; Style["TABLE-LAYOUT"] = tempTableStyle; } } } protected override void OnInit(EventArgs e) { if (0 == Width.Value) Width = new Unit("400px"); if (0 == Height.Value) Height = new Unit("200px"); //Transparent header is not allowed. if (HeaderStyle.BackColor.IsEmpty) { HeaderStyle.BackColor = Color.White; } //Transparent pager is not allowed. if (PagerStyle.BackColor.IsEmpty) { PagerStyle.BackColor = Color.White; } base.OnInit (e); } [Browsable(false)] public override bool ShowHeader { get { return true; } set { if (false == value) throw new InvalidOperationException("Use the original DataGrid to set ShowHeaders to false."); } } } } |
请发表评论