Wednesday, May 11, 2011

Using a Tree View/Asp.net/C#/IronSpeed


Using a Tree View

A Tree View can be used in an Iron Speed Designer application to display hierarchical data from the database, and when the user selects one of the nodes, the relevant information can be displayed to the user on the right.

In the example below, a tree view is used to display a list of products organized hierarchically within each category.  The user can expand any Category and then select a Product.  The details of the selected Product will be displayed on the right.



Iron Speed Designer allows a tree view control to be easily integrated into applications, and populate it with data from the database.  The Selected Node Changed event handler is implemented to display the selected product to the right of the tree view.
In this example, an ASP:TreeView control is added to the spreadsheet grid within the Design Mode for a page. The tree control is populated dynamically when a user expands or collapses a particular section of the tree.  A Populate function is called to fill the sub-tree whenever the user expands a section of the tree.  The Populate function will populate the tree with either Categories or with the list of Products within a Category.  An event handler is implemented to handle the selection of a specific node to display information about the product on the right.
This example extends a Show Product record page built using Iron Speed Designer.  The Southwind database included with Iron Speed Designer is used for this application.  Normally, the Show Product record page displays the Product based on the URL parameter. This page will be extended to display the Product selected in the Tree View.  The initial display of the product specified by the URL will continue to work as-is.
The first few steps insert the tree view into the page layout, and the following steps implement the callback functions to populate the tree, and handle the selection of a node.

Layout Changes

Step 1Create space for a tree view:  Go to the Design mode on the Show Product page. Zoom out to the ShowProduct.aspx.



 


Step 2: Move the ProductsRecordControl two columns to the right to allocate space on the page for the Tree View control in the Quick Layout. The second column will be used to add a HTML space character  (   )  to separate the tree view from the product record control.



 
Step 3. (Optional) Delete all the controls in the Cell with the ProductsTabContainer and replace it with a HTML space  (   ) in the cell editor.
 

Step 4: Insert Tree View: Select the top-left cell A1. Copy and paste the following asp:TreeView Control into the Cell Editor.


Code:


TreeView Properties: The inserted tree view specifies a number properties as described below:


Property
Description
ID
Id of the tree view control (tvCategories).
runat
Indicates the ability to access this control in the code-behind.
Font-Names
Font used to display entries in the tree view.
ForeColor
The foreground text color.
ExpandDepth
The initial expansion shown to the user.
ExpandImageUrl
The image shown to indicate a node can be expanded.
CollapseImageUrl
The image shown to indicate a node can be collapsed.
OnTreeNodePopulate
The code-behind function to be called when a user clicks the node for expansion.  This function will populate the products within a category.
OnSelectedNodeChanged
The code-behind function to be called when a user selects a leaf node.  This function updates the product record on the right.
SelectedNodeStyle-BackColor
The background color to use to display a selected node.
SelectedNodeStyle-ForeColor
The foreground color to use to display a selected node.
Nodes
A substructure that specifies the initial list of nodes in the tree view.  Only the top-level node is included at this point, and the sub-nodes will be added by NodePopulate function when it is called when the user expands a node.
LevelStyles
The styles for each of the levels. There will be three levels, so the styles for each of the three levels are defined.  Currently they are the same styles, but could be different.

Step 5: Align Tree View to the top of the cell:  By default, all content in the cell is shown center-aligned vertically.  To display the tree view at the top, right-click and select Align, Top.




Code Changes

The following steps populate the tree view nodes, and handle the selection of a product and display the updated record control on the right.
Step 6: Implement Node_Populate:  The Node_Populate method is called to populate any of the nodes in the tree control.  Node_Populate will be called either for the second-level (Category) or the third-level (Products within a Category).  Based on the level, either the FillCategories or the FillProductsForCategories is called to populate the tree view appropriately.
The name of the populate method (Node_Populate) is specified on the OnTreeNodePopulate property set on the Tree View control on the layout changes.
This code is inserted into the Section 1 of the code-behind file for the page (not the Controls code-behind file).  Click the ShowProducts.aspx.vb tab, and expand the region “Section 1”.


Copy and paste the code below:
[C#]
Code:
public void Node_Populate(object sender, System.Web.UI.WebControls.TreeNodeEventArgs e) 
{ 
if (e.Node.ChildNodes.Count == 0) { 
switch (e.Node.Depth) { 
case 0: 
// If the parent is the top-level node, then fill with Categories 
FillCategories(e.Node); 
break; // TODO: might not be correct. Was : Exit Select 

case 1: 
// If the parent is a category (depth=1), then fill with Products for the selected Catetory 
FillProductsForCategories(e.Node); 
break; // TODO: might not be correct. Was : Exit Select 

} 
} 
} 

private void FillCategories(TreeNode parent) 
{ 
// Get all records - whereClause is Nothing 
foreach (CategoriesRecord rec in CategoriesTable.GetRecords(null)) { 
// Make sure to populate the Text as the Name, and the Value as the ID so we can 
// use it later when reading the Products for the selected Category ID. 
TreeNode node = new TreeNode(rec.CategoryName, rec.CategoryID.ToString()); 
// Populate when needed - this will ensure that only the first level is populated 
// when tree is first displayed. 
node.PopulateOnDemand = true; 
// Expand when selected. 
node.SelectAction = TreeNodeSelectAction.Expand; 

parent.ChildNodes.Add(node); 
} 
} 

private void FillProductsForCategories(TreeNode parent) 
{ 
// parent.Value will be CategoryId 
// So create a WhereClause that looks like: 
// CategoryId = 34 
// If CategoryId is 34. 
string whereStr = ProductsTable.CategoryID.UniqueName + " = " + parent.Value;
foreach (ProductsRecord rec in ProductsTable.GetRecords(whereStr))
{ 
// Populate the tree node with the name of the product and Product ID. 
// ProductID will be used in the CreateWhereClause to display the correct product. 
TreeNode node = new TreeNode(rec.ProductName, rec.ProductID.ToString()); 
// No sub nodes to populate, so the PopulateOnDemand is False 
node.PopulateOnDemand = false; 
// Display as Selected 
node.SelectAction = TreeNodeSelectAction.Select; 
parent.ChildNodes.Add(node); 
} 
} 

public void Node_Changed(object sender, EventArgs e) 
{ 
// We need to refresh the Products Record panel on the right - so 
// first null out the current record by setting the RecordUniqueId = Nothing 
// Then load data on the page again. 
this.ProductsRecordControl.RecordUniqueId = null; 
LoadData(); 
}

[VB]
Code:
Public Sub Node_Populate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs)
If e.Node.ChildNodes.Count = 0 Then
Select Case e.Node.Depth
Case 0
' If the parent is the top-level node, then fill with Categories
FillCategories(e.Node)
Exit Select
Case 1
' If the parent is a category (depth=1), then fill with Products for the selected Catetory
FillProductsForCategories(e.Node)
Exit Select
End Select
End If
End Sub

Private Sub FillCategories(ByVal parent As TreeNode)
Dim rec As CategoriesRecord
' Get all records - whereClause is Nothing
For Each rec In CategoriesTable.GetRecords(Nothing)
' Make sure to populate the Text as the Name, and the Value as the ID so we can
' use it later when reading the Products for the selected Category ID.
Dim node As TreeNode = New TreeNode(rec.CategoryName, rec.CategoryID.ToString)
' Populate when needed - this will ensure that only the first level is populated
' when tree is first displayed.
node.PopulateOnDemand = True
' Expand when selected.
node.SelectAction = TreeNodeSelectAction.Expand

parent.ChildNodes.Add(node)
Next
End Sub

Private Sub FillProductsForCategories(ByVal parent As TreeNode)
Dim rec As ProductsRecord
' parent.Value will be CategoryId
' So create a WhereClause that looks like:
' CategoryId = 34
' If CategoryId is 34.
Dim whereStr As String = ProductsTable.CategoryID.UniqueName & " = " & parent.Value
For Each rec In ProductsTable.GetRecords(whereStr)
' Populate the tree node with the name of the product and Product ID.
' ProductID will be used in the CreateWhereClause to display the correct product.
Dim node As TreeNode = New TreeNode(rec.ProductName, rec.ProductID.ToString)
' No sub nodes to populate, so the PopulateOnDemand is False
node.PopulateOnDemand = False
' Display as Selected
node.SelectAction = TreeNodeSelectAction.Select
parent.ChildNodes.Add(node)
Next
End Sub

Public Sub Node_Changed(ByVal sender As Object, ByVal e As EventArgs)
' We need to refresh the Products Record panel on the right - so
' first null out the current record by setting the RecordUniqueId = Nothing
' Then load data on the page again.
Me.ProductsRecordControl.RecordUniqueId = Nothing
LoadData()
End Sub

Step 7: Implement Node_Changed:  The Node_Changed method is called to whenever a user selects a leaf-node.  The intermediate nodes such as the selection of a category will not raise the  Node_Changed event.
The name of the selected index changed method (Node_Changed) is specified on the OnSelectedNodeChanged property set on the Tree View control on the layout changes.
This code is inserted into the Section 1 of the code-behind file for the page (not the Controls code-behind file).  This code can be inserted right below the Node_Populate method described above.
The Node_Changed event simply sets the UniqueId of the Product Record Control to Nothing or NULL, and calls LoadData.  The page-level LoadData function will call the LoadData for the Product Record Control and load the data for it once again.
A function defined in the next step will ensure that the currently selected product’s data will be displayed in the product record control.
[C#]
Code:
public void Node_Changed(object sender, EventArgs e) 
{ 
// We need to refresh the Products Record panel on the right - so 
// first null out the current record by setting the RecordUniqueId = Nothing 
// Then load data on the page again. 
this.ProductsRecordControl.RecordUniqueId = null; 
LoadData(); 
}

[VB]
Code:
Public Sub Node_Changed(ByVal sender As Object, ByVal e As EventArgs)
' We need to refresh the Products Record panel on the right - so
' first null out the current record by setting the RecordUniqueId = Nothing
' Then load data on the page again.
Me.ProductsRecordControl.RecordUniqueId = Nothing
LoadData()
End Sub
Step 8: Modify CreateWhereClause:  When LoadData for the ProductsRecordControl is called, it in turns calls CreateWhereClause function to create a where clause to load the data from the products table.  Normally the generated CreateWhereClause simply uses the Product Id specified by the “Products” URL parameter.
We will insert a few lines of code at the top of the CreateWhereClause to check if a product node is selected in the tree control.  If a product node is selected, we will instead use the product ID of this selected node to form the where clause.  Otherwise we will let the remainder of the generated code of CreateWhereClause handle the creation of the clause by calling the base CreateWherClause.
To override the CreateWhereClause, go to the ShowProducts.aspx page in the Application Explorer and zoom to the ShowProducts.aspx in the bread crumbs. Next, select the ProductsRecordControl in the Quick Layout.  A series of code tabs are displayed at the bottom next to the Cell Editor.  Select the CreateWhereClause() tab.  The default generated CreateWhereClause is displayed as shown below:



Copy and paste the entire CreateWhereClause function below to replace the existing CreateWhereClause.
[C#]
Code:
public override WhereClause CreateWhereClause() 
{ 
WhereClause wc = new WhereClause(); 
ProductsTable.Instance.InnerFilter = null; 
wc = new WhereClause(); 

// Find the tree view and see if a node is selected.
// If a node is selected, formulate a where clause and return it.
TreeView tv = (TreeView) this.Page.FindControlRecursively("tvCategories"); 
if (!((tv == null)) && !((tv.SelectedNode == null)) && !((tv.SelectedNode.Value == null))) { 
wc.iAND(ProductsTable.ProductID, 
BaseFilter.ComparisonOperator.EqualsTo, 
tv.SelectedNode.Value); 
return wc; 
} 

// Otherwise return the where clause specified by the generated function.
return base.CreateWhereClause(); 
}


[VB]
Code:
Public Overrides Function CreateWhereClause() As WhereClause

Dim wc As WhereClause
ProductsTable.Instance.InnerFilter = Nothing
wc = New WhereClause()

' Find the tree view and see if a node is selected.
' If a node is selected, formulate a where clause and return it.
Dim tv As TreeView = CType(Me.Page.FindControlRecursively("tvCategories"), TreeView)
If Not(IsNothing(tv)) AndAlso Not(IsNothing(tv.SelectedNode)) AndAlso _
Not(IsNothing(tv.SelectedNode.Value)) Then
wc.iAND(ProductsTable.ProductID, _
BaseFilter.ComparisonOperator.EqualsTo, _
tv.SelectedNode.Value)
Return wc
End If

' Otherwise return the where clause specified by the generated function.
Return MyBase.CreateWhereClause()
End Function 

Build and run the application to see tree view and the selected product on the right.


Step 9: (Optional) To reformat the Product Panel to align with the bottom of the TreeView simply cut and paste the two columns containg the SupplierIDLabel and field value to ReorderLevelLabel and field value as shown below.



And paste the controls under the Discontinued Label as shown below.



The final result will be a nicely formatted page with the TreeView and Products Record Panel.

Attached Images:
Click image for larger version - Name: TreeView.JPG, Views: 925, Size: 21.56 KB   Click image for larger version - Name: TreeView1.JPG, Views: 920, Size: 55.79 KB   Click image for larger version - Name: TreeView10.JPG, Views: 879, Size: 31.74 KB   Click image for larger version - Name: TreeView2.JPG, Views: 915, Size: 54.08 KB   Click image for larger version - Name: TreeView3.JPG, Views: 911, Size: 43.27 KB   Click image for larger version - Name: TreeView4.JPG, Views: 901, Size: 30.48 KB   Click image for larger version - Name: TreeView5.JPG, Views: 891, Size: 96.37 KB   Click image for larger version - Name: TreeView6.JPG, Views: 893, Size: 100.09 KB   Click image for larger version - Name: TreeView7.JPG, Views: 889, Size: 34.90 KB   Click image for larger version - Name: TreeView8.JPG, Views: 884, Size: 47.73 KB   Click image for larger version - Name: TreeView9.JPG, Views: 884, Size: 59.99 KB  


Attached Files:
doc Using_Tree_View.doc (379.00 KB, 109 views)

1 comment: