using System; using System.Web; using System.Web.UI; using System.IO; using System.Data; using System.Diagnostics; namespace techtalk.guamsmrdotcom.customcontrols { /// <summary> /// KUAMSlideShow custom server control, v.1.4.0 /// Written by Jason Salas, MBA, MCP - jason@kuam.com /// </summary> /// <remarks> /// This control allows a page developer to assign a XML data file and refresh rate to populate an automated slide show for the Web. /// The best thing about this control is that the page developer can use any custom XML scheme she wishes, containing /// any number of elements and custom tags. /// </remarks> /// <example> /// The following code shows how to programmatically use this custom server control on an ASP.NET page. /// <code> /// KUAMSlideShow slides = new KUAMSlideShow(); /// slides.DataFile = "slidecontents.xml"; /// slides.RefreshRate = 9; /// </code> /// </example> public class KUAMSlideShow : Control { /// <summary>Private member storing the user-defined filename of a remote XML file containing images, links</summary> private string _datafile; /// <summary>Private member storing the user-defined rate (in seconds) the page is refreshed</summary> private int _refreshrate; /// <summary>Private member stoing the index of the slide currently being displayed</summary> private int _currentslide; /// <summary>Private member storing the total number of slides (element nodes) in the remote XML file</summary> private int _numberofslides; /// <summary> /// Public property that allows the page developer to programmatically/declaratively assign the name /// of an XML file to be used to store slide show data. /// </summary> /// <value> /// A string value indicating the virtual path to the XML file. /// </value> /// <returns> /// The full virtual path to the XML file is returned. /// </returns> public string DataFile { get { if(_datafile == null) throw new Exception("The KUAM SlideShow control requires that you specify a XML file as a data source."); return Context.Server.MapPath(_datafile); } set { _datafile = value; } } /// <summary> /// Public property that allows the page developer to programmatically/declaratively assign the number of /// seconds that the parent page holding the custom server control is refreshed. /// </summary> /// <value> /// An integer value indicating the number of seconds in between page refreshes. /// </value> /// <returns> /// The value in milliseconds is returned. /// </returns> public int RefreshRate { get { int secs = (_refreshrate != 0) ? _refreshrate : 0; return _refreshrate*1000; } set { _refreshrate = value; } } /// <summary> /// Private helper method that builds a jagged array of slides with information by reading data from a remote XML file. /// </summary> /// <param name="filepath"> /// The physical location on disk of the XML file (the value of the DataFile public property). /// </param> /// <returns> /// A jagged string array of slides and slide contents. /// </returns> private string[][] ReadSlides(string filepath) { FileStream fs = new FileStream(filepath,FileMode.Open,FileAccess.Read); StreamReader sr = new StreamReader(fs); DataSet ds = new DataSet(); ds.ReadXml(sr); fs.Close(); DataTable table = ds.Tables[0]; DataRow[] rows = table.Select(); string[][] contents = new string[rows.Length][]; for(int i=0;i<rows.Length;i++) { contents[i] = GetArrayContents(i,table,rows); } return contents; } /// <summary> /// A private helper method automating the population of the jagged string array in the private helper method ReadSlides(). /// </summary> /// <param name="rowNumber"> /// The specific row of type integer in the jagged string array being populated (increments automatically). /// </param> /// <param name="table"> /// The name of the DataTable object populating the jagged string array. /// </param> /// <param name="rows"> /// An array of rows (DataRow[]) populating the specific element in the jagged string array. /// </param> /// <returns> /// A string array of values (the second dimension of the jagged string array (string[][]) in the ReadSlides() method). /// </returns> private string[] GetArrayContents(int rowNumber,DataTable table,DataRow[] rows) { string[] arrayContents = new string[table.Columns.Count]; for(int i=0;i<table.Columns.Count;i++) { arrayContents.SetValue(rows[rowNumber][i].ToString(),i); } return arrayContents; } /// <summary> /// Overrides the base class implementation to load view state data persisted in the overriden SaveViewState() method. /// </summary> /// <remarks> /// Trace debugging statements included in-line. /// </remarks> protected override void LoadViewState(object savedState) { HttpContext.Current.Trace.Warn("LoadViewState()","Loading the view state..."); if(savedState != null) { object[] newState = (object[])savedState; if(newState[0] != null) base.LoadViewState(newState[0]); if(newState[1] != null) _datafile = (string)newState[1]; if(newState[2] != null) _refreshrate = (int)newState[2]; if(newState[3] != null) _currentslide = (int)newState[3]; HttpContext.Current.Trace.Warn("_currentslide: " + (int)_currentslide); } } /// <summary> /// Overrides the base class implementation to save/persist data stored in private variables to the Page class' ViewState object. /// </summary> /// <remarks> /// Trace debugging statements included in-line. /// </remarks> protected override object SaveViewState() { HttpContext.Current.Trace.Warn("SaveViewState()","Saving _numberofslides..."); string[][] slides = ReadSlides(DataFile); _numberofslides = slides.Length; HttpContext.Current.Trace.Warn("_numberofslides: " + _numberofslides.ToString()); HttpContext.Current.Trace.Warn("SaveViewState()","Saving ViewState..."); object[] savedViewState = new object[4]; savedViewState[0] = base.SaveViewState(); savedViewState[1] = _datafile; savedViewState[2] = _refreshrate; if(_currentslide+1 > _numberofslides) { savedViewState[3] = 0; } else { savedViewState[3] = _currentslide + 1; } HttpContext.Current.Trace.Warn("_currentslide: " + (int)_currentslide); return savedViewState; } /// <summary> /// Defines the UI for the custom server control. For this example, the KUAM Newsteam Bio pages are written out. /// </summary> protected override void Render(HtmlTextWriter output) { // Ensure this custom server control is nested within a parent page's server-side <FORM> tags if(Page != null) { Page.VerifyRenderingInServerForm(this); } /* Defines a client-side JavaScript subroutine written to the parent page, using the integer value in the public property RefreshRate to determine how often the parent page the custom server control sits on will get reloaded. */ string clientCode = "<!-- SHOW THE NEXT SLIDE EVERY " + Convert.ToString(RefreshRate/1000) + " SECONDS -->\n\t\t"; clientCode += "<script language=\"JavaScript\">\n\t\t\t"; clientCode += "var intervalID;\n\t\t\t"; clientCode += "intervalID = window.setInterval(\"nextSlide()\"," + RefreshRate.ToString() + ");\n\t\t\t"; clientCode += "function nextSlide() { document.forms[0].submit();}\n\t\t"; clientCode += "</script>\n\t\n\n\n"; output.Write(clientCode); string[][] slides = ReadSlides(DataFile); int i = _currentslide; if(i > slides.Length-1) { i = 0; output.Write("End of show."); } else { for(int j=0;j<slides[i].Length;j=j+slides[i].Length) { output.AddAttribute(HtmlTextWriterAttribute.Width,"405"); output.AddAttribute(HtmlTextWriterAttribute.Border,"0"); output.RenderBeginTag(HtmlTextWriterTag.Table); // <table> output.RenderBeginTag(HtmlTextWriterTag.Tr); // <tr> output.AddAttribute(HtmlTextWriterAttribute.Bordercolor,"#FFFFFF"); output.AddAttribute(HtmlTextWriterAttribute.Bgcolor,"#FFFFFF"); output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily,"Verdana,Arial,Tahoma,sans serif"); output.AddStyleAttribute(HtmlTextWriterStyle.FontSize,"28"); output.AddStyleAttribute(HtmlTextWriterStyle.Color,"#000080"); output.AddStyleAttribute(HtmlTextWriterStyle.FontWeight,"bold"); output.RenderBeginTag(HtmlTextWriterTag.Td); // <td> output.Write("{0}",slides[i][1].ToString()); output.RenderEndTag(); // </td> output.RenderEndTag(); // </tr> output.RenderBeginTag(HtmlTextWriterTag.Tr); // <tr> output.AddAttribute(HtmlTextWriterAttribute.Width,"397"); output.AddAttribute(HtmlTextWriterAttribute.Bgcolor,"#000080"); output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily,"Arial"); output.AddStyleAttribute(HtmlTextWriterStyle.Color,"#FFFFFF"); output.AddStyleAttribute(HtmlTextWriterStyle.FontWeight,"bold"); output.AddStyleAttribute(HtmlTextWriterStyle.FontSize,"20"); output.RenderBeginTag(HtmlTextWriterTag.Td); // <td> output.Write("{0}",slides[i][2].ToString()); output.RenderEndTag(); // </td> output.RenderEndTag(); // </tr> output.RenderEndTag(); // </table> output.Write("<br/>\t\t<center><img src=\"{0}\" alt=\"{1}\" src=\"{1}\"/></center><hr width=\"35%\" color=\"#000080\" size=\"1\"/>{2}\n",slides[i][0].ToString(),slides[i][1].ToString(),slides[i][3].ToString()); } } } } }