College.NET Source Code - AnchorCloud Sample

The central component of the College.NET application is the AnchorCloud control. It is a databound custom web control that renders a cloud/grid of hyperlinks with appropriate tooltips, comments, and formatting. All source code markup was produced by the excellent Copy As HTML Visual Studio extension.


    1 using System;
    2 using System.Collections;
    3 using System.Text;
    4 using System.Web;
    5 using System.Web.UI;
    6 using System.Web.UI.WebControls;
    7 
    8 // The AnchorCloud control is a Databound control.
    9 // It is bound to the results of the qCollegeReflections query.
   10 // It renders the underlying data as a grid/cloud of hyperlinks.
   11 // The control also tries to minimize the size of the output by tracking style changes.
   12 
   13 namespace CollegeCSharp
   14 {
   15     [ToolboxData("<{0}:AnchorCloud runat=server></{0}:AnchorCloud>")]
   16     public class AnchorCloud : DataBoundControl
   17     {
   18 
   19         public enum RenderStyles
   20         {
   21             Cloud = 0,
   22             Grid = 1
   23         }
   24 
   25         // Public property placeholders
   26         private RenderStyles _renderStyle;
   27 
   28         // Support Databound control properties
   29         private IEnumerable _data;
   30         private string _dataTextField = string.Empty;
   31         private string _sortExpression = string.Empty;
   32 
   33         // Non-breaking hyphen depends on browser type
   34         // Calculate it once, then store it here
   35         private string _nonBreakingHyphen;
   36 
   37 
   38         // Specify how the the control is rendered.
   39         // Valid choices are to render as a grid or as a cloud (of hyperlinks)
   40         public RenderStyles RenderStyle
   41         {
   42             get { return _renderStyle; }
   43             set { _renderStyle = value; }
   44         }
   45 
   46 
   47         // Specify how to sort the output from the underlying data object
   48         // Value is passed through to underlying databound control methods
   49         public string SortExpression
   50         {
   51             get { return _sortExpression; }
   52             set { _sortExpression = value; }
   53         }
   54 
   55 
   56         // Override WebControl.RenderContents
   57         // Call the appropriate routine, depending on the render mode.
   58         protected override void RenderContents(HtmlTextWriter writer)
   59         {
   60             PrepareNonBreakingHyphen(writer);
   61 
   62             if (DesignMode)
   63             {
   64                 RenderDesigner(writer);
   65                 return;
   66             }
   67 
   68             switch (RenderStyle)
   69             {
   70                 case RenderStyles.Grid:
   71                     RenderGrid(writer);
   72                     break;
   73                 default:
   74                     RenderCloud(writer);
   75                     break;
   76             }
   77         }
   78 
   79 
   80         // Override of DataBoundControl.PerformSelect method
   81         // Bind the control to the specified datasource
   82         protected override void PerformSelect()
   83         {
   84             // This is the Microsoft recommended approach to implementing a databound control.
   85             // It would be better if it were encapsulated in a class/interface.
   86             // However, since this is a one-off project, just use it directly.
   87 
   88             DataSourceSelectArguments dataSourceSelectArguments;
   89             DataSourceView dataSourceView;
   90 
   91             if (!IsBoundUsingDataSourceID)
   92             {
   93                 this.OnDataBinding(EventArgs.Empty);
   94             }
   95 
   96             dataSourceView = this.GetData();
   97 
   98             dataSourceSelectArguments = new DataSourceSelectArguments();
   99             if (dataSourceView.CanSort == true)
  100             {
  101                 if (this.SortExpression.Length > 0)
  102                 {
  103                     dataSourceSelectArguments.SortExpression = this.SortExpression;
  104                 }
  105             }
  106 
  107             dataSourceView.Select(dataSourceSelectArguments, PerformDataBinding);
  108 
  109             RequiresDataBinding = false;
  110             MarkAsDataBound();
  111             OnDataBound(EventArgs.Empty);
  112         }
  113 
  114         // Override DataBoundControl.PerformDataBinding
  115         // This is called when the asynchronous DataSourceView.Select() method completes
  116         protected override void PerformDataBinding(System.Collections.IEnumerable data)
  117         {
  118             base.PerformDataBinding(data);
  119 
  120             // Store a local copy of the data for later use
  121             _data = data;
  122         }
  123 
  124 
  125         // Render design mode version of control (silver block with control ID)
  126         private void RenderDesigner(HtmlTextWriter writer)
  127         {
  128             writer.Write("<table cellpadding=4 cellspacing=0 bordercolor=black border=1>");
  129             writer.Write("<tr>");
  130             writer.Write("<td bgcolor=silver>");
  131             writer.Write("<b>AnchorCloud</b> - " + this.ID);
  132             if (this.DataSourceID.Length > 0)
  133             {
  134                 writer.Write(" (DataBound - " + HttpUtility.HtmlEncode(this.DataSourceID) + ")");
  135             }
  136             else
  137             {
  138                 writer.Write(" (Unbound)");
  139             }
  140             writer.Write("</td></tr></table></span>");
  141             return;
  142         }
  143 
  144 
  145         // Render contents of control as a Cloud (series of Html Hyperlinks)
  146         private void RenderCloud(HtmlTextWriter writer)
  147         {
  148             int reflectionID;
  149             int rating;
  150             string shortName;
  151             string hyperlink;
  152             string tooltip;
  153             string course;
  154 
  155             int fontSize;
  156             bool fontBold;
  157             int lastFontSize;
  158             bool fontNeedsEndTag;
  159 
  160             string htmlClass;
  161 
  162             writer.BeginRender();
  163 
  164             writer.AddAttribute("class", "CloudView", false);
  165             writer.RenderBeginTag("span");
  166 
  167             if (!_data.GetEnumerator().MoveNext())
  168             {
  169                 writer.Write("No records match your criteria");
  170             }
  171 
  172             fontSize = 3;
  173             lastFontSize = 3;
  174             fontBold = false;
  175             writer.AddAttribute("size", Convert.ToString(fontSize), false);
  176             writer.RenderBeginTag("font");
  177             fontNeedsEndTag = false;
  178 
  179             foreach (object dataElement in _data)
  180             {
  181                 reflectionID = Convert.ToInt32(DataBinder.GetPropertyValue(dataElement, "ReflectionID"));
  182                 rating = Convert.ToInt32(DataBinder.GetPropertyValue(dataElement, "Rating"));
  183                 shortName = CStrSafe(DataBinder.GetPropertyValue(dataElement, "ShortName"));
  184                 hyperlink = CStrSafe(DataBinder.GetPropertyValue(dataElement, "Hyperlink"));
  185                 course = CStrSafe(DataBinder.GetPropertyValue(dataElement, "CourseNumber")) + " - " + CStrSafe(DataBinder.GetPropertyValue(dataElement, "CourseName"));
  186                 tooltip = CStrSafe(DataBinder.GetPropertyValue(dataElement, "Tooltip"));
  187                 if (tooltip.Length > 0)
  188                 {
  189                     tooltip = tooltip + " (" + course + ")";
  190                 }
  191                 else
  192                 {
  193                     tooltip = course;
  194                 }
  195 
  196                 htmlClass = "R" + rating;
  197                 fontSize = 3;
  198                 fontBold = false;
  199                 switch (rating)
  200                 {
  201                     case 1:
  202                         fontSize = 3;
  203                         fontBold = true;
  204                         break;
  205                     case 2:
  206                         fontSize = 4;
  207                         fontBold = false;
  208                         break;
  209                     case 3:
  210                         fontSize = 4;
  211                         fontBold = true;
  212                         break;
  213                     case 4:
  214                         fontSize = 5;
  215                         fontBold = true;
  216                         break;
  217                     case 5:
  218                         fontSize = 6;
  219                         fontBold = true;
  220                         break;
  221                 }
  222 
  223                 if (fontSize > 6)
  224                 {
  225                     fontSize = 6;
  226                 }
  227 
  228                 if (fontSize != lastFontSize)
  229                 {
  230                     if (fontNeedsEndTag)
  231                     {
  232                         writer.RenderEndTag();
  233                         // font
  234                         fontNeedsEndTag = false;
  235                         lastFontSize = 3;
  236                     }
  237                 }
  238 
  239                 writer.Write(" &nbsp;&nbsp; ");
  240                 writer.Write(Environment.NewLine);
  241 
  242                 if (fontSize != lastFontSize)
  243                 {
  244                     writer.AddAttribute("size", Convert.ToString(fontSize), false);
  245                     writer.RenderBeginTag("font");
  246                     fontNeedsEndTag = true;
  247                     lastFontSize = fontSize;
  248                 }
  249 
  250                 if (fontBold)
  251                 {
  252                     writer.RenderBeginTag("b");
  253                 }
  254 
  255                 if (hyperlink.Length > 0)
  256                 {
  257                     writer.AddAttribute("href", hyperlink, true);
  258                     if (tooltip.Length > 0)
  259                     {
  260                         writer.AddAttribute("title", tooltip, true);
  261                     }
  262                     writer.AddAttribute("class", htmlClass, false);
  263 
  264                     writer.RenderBeginTag("a");
  265                     writer.Write(HtmlEncodedNonBreakingText(shortName));
  266                     writer.RenderEndTag();
  267                 }
  268                 else
  269                 {
  270                     if (tooltip.Length > 0)
  271                     {
  272                         writer.AddAttribute("class", htmlClass, false);
  273                         writer.AddAttribute("title", tooltip, true);
  274                         writer.RenderBeginTag("span");
  275                         writer.RenderBeginTag("u");
  276                     }
  277 
  278                     writer.Write(HtmlEncodedNonBreakingText(shortName));
  279 
  280                     if (tooltip.Length > 0)
  281                     {
  282                         writer.RenderEndTag();
  283                         // u
  284                         writer.RenderEndTag();
  285                         // span
  286                     }
  287                 }
  288 
  289                 if (fontBold)
  290                 {
  291                     writer.RenderEndTag();
  292                     // b
  293                 }
  294 
  295                 writer.Flush();
  296             }
  297 
  298             if (fontNeedsEndTag)
  299             {
  300                 writer.RenderEndTag();
  301                 // font
  302             }
  303 
  304             writer.RenderEndTag();
  305             // font
  306 
  307             writer.RenderEndTag();
  308             // span
  309 
  310             writer.EndRender();
  311         }
  312 
  313 
  314         // Render contents of control as a Grid (Html Table)
  315         private void RenderGrid(HtmlTextWriter writer)
  316         {
  317             int rating;
  318             string shortName;
  319             string hyperlink;
  320             string tooltip;
  321             string courseNumber;
  322             string courseName;
  323             string course;
  324             string semester;
  325 
  326             int fontSize;
  327             bool fontBold;
  328 
  329             int recordCount;
  330 
  331             string htmlClass;
  332 
  333             writer.BeginRender();
  334 
  335             writer.AddAttribute("class", "GridView", false);
  336             writer.RenderBeginTag("span");
  337 
  338             recordCount = 0;
  339             if (!_data.GetEnumerator().MoveNext())
  340             {
  341                 writer.Write("No records match your criteria");
  342                 return;
  343             }
  344 
  345             writer.AddAttribute("border", "1", false);
  346             writer.AddAttribute("cellpadding", "4", false);
  347             writer.AddAttribute("cellspacing", "0", false);
  348             writer.Write(Environment.NewLine);
  349             writer.RenderBeginTag("table");
  350 
  351             writer.AddAttribute("bgcolor", "silver", false);
  352             writer.Write(Environment.NewLine);
  353             writer.RenderBeginTag("thead");
  354 
  355             writer.Write(Environment.NewLine);
  356             writer.RenderBeginTag("th");
  357             writer.Write("Semester");
  358             writer.RenderEndTag();
  359 
  360             writer.Write(Environment.NewLine);
  361             writer.RenderBeginTag("th");
  362             writer.Write("Course Number");
  363             writer.RenderEndTag();
  364 
  365             writer.Write(Environment.NewLine);
  366             writer.RenderBeginTag("th");
  367             writer.Write("Course Name");
  368             writer.RenderEndTag();
  369 
  370             writer.Write(Environment.NewLine);
  371             writer.RenderBeginTag("th");
  372             writer.Write("Subject");
  373             writer.RenderEndTag();
  374 
  375             writer.Write(Environment.NewLine);
  376             writer.RenderBeginTag("th");
  377             writer.Write("Description");
  378             writer.RenderEndTag();
  379 
  380             writer.RenderEndTag();
  381             // thead
  382 
  383             foreach (object dataElement in _data)
  384             {
  385 
  386                 recordCount = recordCount + 1;
  387 
  388                 writer.Write(Environment.NewLine);
  389                 writer.RenderBeginTag("tr");
  390 
  391                 rating = Convert.ToInt32(DataBinder.GetPropertyValue(dataElement, "Rating"));
  392                 shortName = CStrSafe(DataBinder.GetPropertyValue(dataElement, "ShortName"));
  393                 hyperlink = CStrSafe(DataBinder.GetPropertyValue(dataElement, "Hyperlink"));
  394                 courseNumber = CStrSafe(DataBinder.GetPropertyValue(dataElement, "CourseNumber"));
  395                 courseName = CStrSafe(DataBinder.GetPropertyValue(dataElement, "CourseName"));
  396                 course = courseNumber + " - " + courseName;
  397                 semester = CStrSafe(DataBinder.GetPropertyValue(dataElement, "Semester")) + " " + CStrSafe(DataBinder.GetPropertyValue(dataElement, "Year"));
  398                 tooltip = CStrSafe(DataBinder.GetPropertyValue(dataElement, "Tooltip"));
  399 
  400                 htmlClass = "R" + rating;
  401                 fontSize = 3;
  402                 fontBold = false;
  403                 switch (rating)
  404                 {
  405                     case 1:
  406                         fontSize = 3;
  407                         fontBold = true;
  408                         break;
  409                     case 2:
  410                         fontSize = 4;
  411                         fontBold = false;
  412                         break;
  413                     case 3:
  414                         fontSize = 4;
  415                         fontBold = true;
  416                         break;
  417                     case 4:
  418                         fontSize = 5;
  419                         fontBold = false;
  420                         break;
  421                     case 5:
  422                         fontSize = 5;
  423                         fontBold = true;
  424                         break;
  425                 }
  426 
  427                 if (fontSize > 6)
  428                 {
  429                     fontSize = 6;
  430                 }
  431 
  432                 writer.AddAttribute("valign", "top", false);
  433                 writer.Write(Environment.NewLine);
  434                 writer.RenderBeginTag("td");
  435                 writer.Write(HtmlEncodedNonBreakingText(semester));
  436                 writer.RenderEndTag();
  437 
  438                 writer.AddAttribute("valign", "top", false);
  439                 writer.Write(Environment.NewLine);
  440                 writer.RenderBeginTag("td");
  441                 writer.Write(HtmlEncodedNonBreakingText(courseNumber));
  442                 writer.RenderEndTag();
  443 
  444                 writer.AddAttribute("valign", "top", false);
  445                 writer.Write(Environment.NewLine);
  446                 writer.RenderBeginTag("td");
  447                 writer.Write(HttpUtility.HtmlEncode(courseName));
  448                 writer.RenderEndTag();
  449 
  450                 writer.AddAttribute("valign", "top", false);
  451                 writer.Write(Environment.NewLine);
  452                 writer.RenderBeginTag("td");
  453 
  454                 if (fontSize != 3)
  455                 {
  456                     writer.AddAttribute("size", Convert.ToString(fontSize), false);
  457                     writer.RenderBeginTag("font");
  458                 }
  459 
  460                 if (fontBold)
  461                 {
  462                     writer.RenderBeginTag("b");
  463                 }
  464 
  465                 if (hyperlink.Length > 0)
  466                 {
  467                     writer.AddAttribute("class", htmlClass, false);
  468                     writer.AddAttribute("href", hyperlink, true);
  469                     writer.RenderBeginTag("a");
  470                     writer.Write(HttpUtility.HtmlEncode(shortName));
  471                     writer.RenderEndTag();
  472                 }
  473                 else
  474                 {
  475                     writer.AddAttribute("class", htmlClass, false);
  476                     writer.RenderBeginTag("span");
  477                     writer.Write(HttpUtility.HtmlEncode(shortName));
  478                     writer.RenderEndTag();
  479                 }
  480 
  481                 if (fontBold)
  482                 {
  483                     writer.RenderEndTag();
  484                     // b
  485                 }
  486 
  487                 if (fontSize != 3)
  488                 {
  489                     writer.RenderEndTag();
  490                     // font
  491                 }
  492 
  493                 writer.RenderEndTag();
  494                 // td
  495 
  496                 writer.AddAttribute("valign", "top", false);
  497                 writer.Write(Environment.NewLine);
  498                 writer.RenderBeginTag("td");
  499                 if (tooltip.Length > 0)
  500                 {
  501                     writer.Write(HttpUtility.HtmlEncode(tooltip));
  502                 }
  503                 else
  504                 {
  505                     writer.Write("&nbsp;");
  506                 }
  507 
  508                 writer.RenderEndTag();
  509                 // td
  510 
  511                 writer.RenderEndTag();
  512                 // tr
  513 
  514                 writer.Flush();
  515             }
  516 
  517             writer.RenderEndTag();
  518             // table
  519 
  520             writer.RenderEndTag();
  521             // span
  522 
  523             writer.EndRender();
  524         }
  525 
  526 
  527         // Prevent output from being wrapped by the browser (keep words together)
  528         private string HtmlEncodedNonBreakingText(string text)
  529         {
  530             if (text.Length == 0)
  531             {
  532                 return string.Empty;
  533             }
  534 
  535             string result;
  536 
  537             result = text;
  538 
  539             result = HttpUtility.HtmlEncode(result);
  540             result = result.Replace(" ", "&nbsp;");
  541             result = result.Replace("-", _nonBreakingHyphen);
  542 
  543             return result;
  544         }
  545 
  546         // String conversion might need to change depending on type.
  547         // Therefore, encapsulate the function here, just in case it needs to change later
  548         private string CStrSafe(object item)
  549         {
  550             return item.ToString();
  551         }
  552 
  553 
  554         // Not all browsers deal with non-breaking hypens equally.
  555         // This function will determine the best character to use.
  556         public void PrepareNonBreakingHyphen(HtmlTextWriter writer)
  557         {
  558             string browser;
  559 
  560             _nonBreakingHyphen = "&#8209;";
  561             // equivalent "&#x2011;"
  562 
  563             // Check if Browser object is available
  564             if (this.DesignMode || this.Page == null || this.Page.Request == null || this.Page.Request.Browser == null)
  565             {
  566 
  567                 // Browser object is not available, exit now.
  568                 return;
  569             }
  570 
  571             // Determine which browser is being used
  572             browser = this.Page.Request.Browser.Browser;
  573 
  574             // Choose appropriate non-breaking hyphen character, depending on browser type
  575             switch (browser.ToLowerInvariant())
  576             {
  577                 case "ie":
  578                 case "firefox":
  579                     break;
  580                 // These browsers can render non-breaking hyphens.
  581                 // Therefore, do nothing.
  582                 default:
  583                     // Any other browsers might have problems with rendering non-breaking hyphens.
  584                     // Therefore, use the tilde character instead.
  585                     _nonBreakingHyphen = "~";
  586                     break;
  587             }
  588         }
  589     }
  590 }



Copyright (C) 2007-2009 by Robert Pinchbeck
All Rights Reserved