Thursday, April 2, 2009

Populating a TreeView control from a database

I was recently tasked with creating a navigation control which displayed a list of cities and nested communities for those cities.  As the listings could change at a moments notice and I might not always be available to modify code I decided to use a TreeView control and populate it from a SQL Server table. 

While my end-product looks and acts differently than this example, I will post the mere basics for building a working product.

First a look at the data.   I am pulling information about communities located with a city so the relationship is many communities per city.

Example of the data follows.   The communityID is our primary key and will be used as the value of the selected node.

communityID communityCity                                      communityName
----------- -------------------------------------------------- --------------------------------------------------
1 Cypress Coles Crossing
2 Cypress Bridgeland
3 Cypress Stillwater Village
4 Memorial Terraces on Memorial
5 Richmond Lakes of Bella Terra



Let's drop a TreeView control into our page.  Mine is called tvNav.  I added some images to indicate the state (Collapsed or Expanded) which you see in the markup.




<body>
<form id="form1" runat="server">
<div>
<asp:TreeView ID="tvNav" runat="server"
CollapseImageUrl="~/Testimonials/images/expanded.gif"
ExpandImageUrl="~/Testimonials/images/collapsed.gif">
</asp:TreeView>
</div>
</form>
</body>



Now on the back-end we build our functions to pull the data and populate the TreeView.



The method I chose to use (for no other reason than I felt like it) was to build a DataSet of information pulled from the table.  I then iterate through this dataset for data comparison and extraction.



The first function builds a DataSet and returns it to the function that calls it.




private DataSet BuildDS()
{
string strSQL = "SELECT communityID,communityName,communityCity FROM MYTABLE WHERE communityStatus = 'A' ORDER BY communityCity, communityName";
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MYCONNECTIONSTRING"].ToString());
conn.Open();
SqlDataAdapter sda = new SqlDataAdapter(strSQL, conn);
DataSet ds = new DataSet();
sda.Fill(ds);
conn.Close();

return ds;
}



The workhorse:




private void BuildTree()
{
DataSet ds = BuildDS();
string cCity = "";
if (ds != null)
{

TreeNode parentnode = null;
TreeNode childnode = null;
foreach (DataRow row in ds.Tables[0].Rows)
{
if (cCity.CompareTo(row["communityCity"].ToString()) < 0)
{
parentnode = new TreeNode(row["communityCity"].ToString());
// we want parent nodes to simply expand so no postback (select) is needed
parentnode.SelectAction = TreeNodeSelectAction.Expand;
if (parentnode != null)
{
tvNav.Nodes.Add(parentnode);
}
}
cCity = row["communityCity"].ToString();
}

foreach (TreeNode tn in tvNav.Nodes)
{
foreach (DataRow row in ds.Tables[0].Rows)
{
if (tn.Text.CompareTo(row["communityCity"]) == 0)
{
childnode = new TreeNode();
childnode.Text = row["communityName"].ToString();
childnode.Value = row["communityID"].ToString();
tn.ChildNodes.Add(childnode);
}
}
tn.Collapse();
}
}
}




First thing we do is to add the Parent nodes to the Treeiew.  As the CITY is the parent in the data's relationship schema we'll use that as the value for our Parent nodes in the control. To add those nodes I iterate through each row in the dataset and compare the value of the stored City with the value of the cCity string element.  In the first run through of the loop we have "null" as the value of cCity since nothing's been assigned as the value.  After we process our actions for each iteration though we assign the current value of the City field in the dataset to the cCity element.



After our parents are populated we make another loop through our dataset to build child nodes to add to the parents.  To accomplish this we use 2 loops.  The first loop moves through the parent nodes.  The nested loop inside compares the value of the parent node text with the value of the "communityCity" data-element.  If they are the same, we know to add a child node.  If not we simply move on to the next.



Note:  If your results-set (either in your SQL statement or via filtering your Dataset) are not in the correct order, this method won't work.   if you look at the SQL query statement I've used, you see it's ordered by communityCity and then by communityName. 



Finally we call our BuildTree() function so our control is built.  I do this on the initial creation of the page so that subsequent postbacks don't create additional nodes.




protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
BuildTree();   }
}

Friday, March 6, 2009

Strip HTML from TextBox inputs

Use a regular expression to search for HTML variants and convert them to "" (nothing).

 

I've placed a simple function called StripHTML in a user-class called SystemFunctions as follows:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text.RegularExpressions;

public class SystemFunctions
{
public string StripHTML(string strInput)
{
return System.Web.HttpContext.Current.Server.HtmlDecode(Regex.Replace(strInput, "<(.|\n)*?>", ""));
}
}



* Make sure you add the reference to System.Text.RegularExpressions

Wednesday, September 17, 2008

Conditional ModalPopupExtender as UpdateProgress control

I'm a big fan of Matt Berseth's blog and his articles are some of the most clear, concise ones out there when dealing with UI elements and webcontrols for ASP.NET.   I've happily employed his ModalPopup as an AJAX Progress Indicator example in a project I'm working on but ran into a small hitch.

Matt's Indicator envelops the beauty of simplicity in that it simply calls the ModalPopupExtender's show() and hide() events when the page's requestmanager receives a request from the Scriptmanager.

One of my pages contains a fairly dense GridView which reflects data that's changed quite often.  As such, I've encapsulated this GridView in an UpdatePanel control and added a Timer control to it with a tick of 20000.   I wanted to show the Modal Progress Indicator when users changed filtering options (controls) for this Gridview but didn't want it to show on postback from the Timer.  After a bit of searching it was as simple as pulling the name of the control that triggered the async call and managing the reaction.

 

<form id="form1" runat="server">
<cc1:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</cc1:ToolkitScriptManager>
<script type="text/javascript" language="javascript">
// register for our events
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
function beginRequest(sender, args)
{
if(args.get_postBackElement().id.toString() != 'NameOfMyTimerControl')
{
// show the popup
$find('NameOfMyPopupExtender').show();
}
}
function endRequest(sender, args)
{
// hide the popup
$find('NameOfMyPopupExtender').hide();
}
</script>


Now my Progress Indicator only shows when users interact with the page and NOT when the timer refreshes the data.


Day 1

Cowboy coding time!

I've created this stop as a repository for shitty code-snippets, excuses for not doing things the "RIGHT" way and overall generalizations of lack-of-technique or foundation when it comes to C#, ASP.NET, AJAX or ADO.NET.

How often do you coders out there - looking for examples of functions or methods which achieve a seemingly simple task - wind up creating your own solution but often wondering if anyone else would benefit? I've lost count of the times but finally decided to do something about it. Sure - some of my examples or codings will contain errors or flaws. Sure they might be downright unintelligible. As long as it works and allows me to continue on a task or project, I'm good with it.

Let the games begin...

Being a programmer and web-developer for close to 15 years now, I've gone through various languages, tools and methodologies.

I've always been one who can get a job or task done in a short amount of time. Lots of that can be attributed to the lack of any disciplined coding or development.
A former co-worker of mine had the fortune of having to maintain an app that I had written. In referring to it on his own blog he coined what he had to work with as "cowboy code", thus the name of my blog.
I'm proud to say I'm a cowboy-coder. One who ignores best-method approaches to coding. One who doesn't care a lick about paired-programming, scrum sessions or TDD. I work from the top - down. I use session variables. I don't comment my code. I hate creating views and love using #temp tables!
Yeah...I'm that guy