<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar/19834389?origin\x3dhttps://netchallenges.blogspot.com', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Put some text here ...

Put some text here ...

Put some text here ...

Put some text here ...

Put some text here ...

Put some text here ...

Saturday, April 29, 2006

Enhanced TreeView Control for Windows Apps






Problem: I need to present summarized data along with controls categorically arranged in some in some kind of a hierarchy. A simple TreeView control allows displaying of small bit of information per node. I needed a TreeView control that allows more complex type of information to be arranged under a tree.

Solution:
An Enhanced TreeView control [click on the screen shots to check it out]. I did not have much time to spend on this, and I havnt really used it yet. The look n' feel of the control is completely customizable. If you find any use for it, then go ahead download it! If you are unable to download it, you may contact me, and I'll send it over to you (FREE ofcourse).

The source code will be shortly released under GNU license. Everyone is encouraged to use, extend, and polish the functionality of the control.

------------TO USE THE CONTROL---------------
The control in the first screen shots was created by the following code:
etv1 = New EnhancedTreeView
'Set Look n' Feel for the EnhancedTreeView control
Me.etv1.AutoScroll = True
Me.etv1.BackColor = System.Drawing.Color.Transparent
Me.etv1.Font = New System.Drawing.Font("Tahoma", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.etv1.Location = New System.Drawing.Point(1, 2)
Me.etv1.Name = "etv1"
Me.etv1.NodeEndColor = System.Drawing.Color.White
Me.etv1.NodeHeight = 20
Me.etv1.NodeStartColor = System.Drawing.Color.Lavender
Me.etv1.NoteLabel = Nothing
Me.etv1.Size = New System.Drawing.Size(512, 372)
Me.etv1.TabIndex = 1

'Build Node list
Me.etv1.NodeList.Add("Root 1")
Me.etv1.NodeList(0).TitleNote = Date.Now.ToShortDateString
Me.etv1.NodeList.Add("Root 2")
Me.etv1.NodeList(1).TitleNote = "By Nomair Kashif"
Me.etv1.NodeList(0).ShowPlus = True
Me.etv1.NodeList(1).ShowPlus = True
Me.etv1.NodeList(0).DetailPanelHeight = 190
Me.etv1.NodeList(0).NodeDetailsPanel.Controls.Add(New MonthCalendar)
Me.etv1.NodeList(1).ChildNodes.Add("Root2 - Child 1")
Me.etv1.NodeList(1).ChildNodes.Add("Root 2- Child 2")
Me.etv1.NodeList(1).ChildNodes(0).ShowPlus = True
Me.etv1.NodeList(1).ChildNodes(1).ShowPlus = True
Me.Controls.Add(etv1)

{END}

Thursday, April 27, 2006

DataView Row Filter Based On Pattern Matching Column(s)

Tested On:
VS Version: 2002 and 2003
.NET Frakework Version 1.1 and 1.0


Problem:
I am trying to filter a set of records retreived from the database based on altering portions of a single column.

For Example: Consider a column, ItemNo to contain values such as C141XX00220052CGVK. The 18 character Item No. consists of diferent meaningful coded parts (as in the figure above).

We have:
1) One column storing ItemNo as varchar (SQL Server 2000)
2) A need to flexibly search and filter records as if each part of the item number were in its own column.

Solution 1:
Use T-SQL LIKE clause.
Problem: LIKE clause does not allows wildcards in the middle of the string. For example:

*C14* - is valid

C34* - is valid

*C4*K4* - is invalid

My Solution:
1) Construct a RegEx regular expression based on the pattern of values (item no. parts) supplied
2)Traverse the DataRowViewCollection of the Defaul DataView object
3)Use RegExp.IsMatch() method to compare the (ItemNo) column value with the regular expression for each DataRow object in the collection
4)Mark rows for delete
5) Delete row(s)

[Source Code Below]

'Simply call doDeepFilter function with column name, and regular expression to match. Then bind the DataView/DataSet object to any data live control.
Me.doDeepFilter("itemNo", getFilterQuery())
rptProductionList.DataSource = dvList
rptProductionList.DataBind()
---------------------------------------------------
Private Sub doDeepFilter(ByVal colName As String, ByVal regExp As String)
Dim deleteArray As New ArrayList
If Me.advanceSearchPanel.Visible Then
For i As Integer = 0 To dvList.Count - 1
If Regex.IsMatch(CType(dvList.Item(i).Row.Item(colName), String), regExp) = False Then
deleteArray.Add(dvList.Item(i).Row)
End If
Next
End If

For Each dr As DataRow In deleteArray
dr.Delete()
Next
End Sub
------------------------------------------------------------------------------------
Private Function getFilterQuery() As String
Dim searchExpression As String
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtitemConductor.MaxLength, Me.txtitemConductor.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtBuild.MaxLength, Me.txtBuild.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtFilm.MaxLength, Me.txtFilm.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtSize.MaxLength, Me.txtSize.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtPackaging.MaxLength, Me.txtPackaging.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtClass.MaxLength, Me.txtClass.Text.ToUpper))
searchExpression = searchExpression.Concat(searchExpression, ParseItemNoToExpression(Me.txtCustomer.MaxLength, Me.txtCustomer.Text.ToUpper))
Return "\b" & searchExpression & "\b"
End Function
--------------------CREATE A REGULAR EXPRESSION DYNAMICALLY--------------
Private Function ParseItemNoToExpression(ByVal characters As Integer, ByVal str As String) As String
Dim strBuilder As New StringBuilder
If str.Length = 0 Then
Return strBuilder.Append("\").Append("w{").Append(characters & "}".Chars(0)).ToString
ElseIf str.Length > 0 And str.Length < style="color: rgb(0, 0, 153);">Then

For Each chr As Char In str
strBuilder.Append("[" & chr & "]")
Next
Return strBuilder.Append("\").Append("w").Append("{" & characters - str.Length & "}".Chars(0)).ToString
Else
Return "[" & str & "]" 'return pattern in regular expression
End If
End Function

Thursday, December 29, 2005

Finding MAC address in VB.NET

Dim mc As System.Management.ManagementClass
Dim mo As ManagementObject
mc = New ManagementClass("Win32_NetworkAdapterConfiguration")
Dim moc As ManagementObjectCollection = mc.GetInstances()
For Each mo In moc
If mo.Item("IPEnabled") = True Then
ListBox1.Items.Add("MAC address " & mo.Item("MacAddress").ToString())
End If
Next

Tuesday, December 27, 2005

Simple Splitter With Handle

Tested On:
VS Version: 2002 and 2003
.NET Frakework Version 1.1 and 1.0

Problem: A splitter control that is not too thick that it takes up too much valuable space, and not too thin that it is difficult for a user to locate.

Solution: A custom splitter with a handle and 3D-look. This solutions is very simple and does not require the complexities of using XP themes, or resource intensive operations of using Win32 native DLLs. [Click Image]1) Add a class or User Control to you Solution
2) Inherit it from System.Windows.Forms.Splitter

Example:
Imports System.Drawing.Text
Imports System.Drawing
Public Class CoolSplitter
Inherits System.Windows.Forms.Splitter

Public Sub New()
MyBase.New()

MyBase.SetStyle(ControlStyles.DoubleBuffer, True)
MyBase.SetStyle(ControlStyles.ResizeRedraw, True)
MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
MyBase.UpdateStyles()
Me.BackColor = System.Drawing.Color.Transparent

End Sub
End Class

3)Notice, The new splitter control CoolSplitter is initialized with certain characteristics. The most important ones are :
- ControlStyles.ResizeRedraw
- ControlStyles.DoubleBuffer
They allow for a flicker-free painting of the control.

4) Next, we need to decide on the new look n' feel for the splitter control. Like mentioned earlier, we need a 3D-lookin splitter control that has a handle drawn in the center. In order to accomplish this task we need to be somewhat familiar with GDI+ classes, and namespaces: System.Drawing and System.Drawing.Text

In order to draw anything on the surface of a control we need to get the controls Graphics object. The Graphics object represents all elements of a control that are visual and is responsible for drawing color,shades,shapes, etc. Do not create a new instance of a Graphics object, instead get the current instance, and modify that. The best place to change a controls look is right before it is painted (OnPaint method):
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim display As Graphics = e.Graphics
'Code to draw goes here...
End Sub

There are two objects we need to draw.
1) 3D-surface
2) A hadle

3D-Surface
To draw a 3D surface, we use the Graphics object's FillRectangle method and supply it with a special kind of brush, Drawing.Drawing2D.LinearGradientBrush. This brush paints two colors fading into each other.
Example:
Dim mybrush As Drawing.Drawing2D.LinearGradientBrush
mybrush = New Drawing.Drawing2D.LinearGradientBrush(New PointF(0, 0), New PointF(0, Me.Height - 1), System.Drawing.SystemColors.ControlLight, Drawing.SystemColors.ControlDark)
display.FillRectangle(mybrush, New Drawing.Rectangle(0, 0, Me.Width, Me.Height))

The two color used are
System.Drawing.SystemColors.ControlLigh (begin color) and
System.Drawing.SystemColors.ControlDark (ending color).

A Handle

We use the same technique here, but use a different style of Brush object -- a HatchBrush
Example:
Dim myrect As RectangleF = New RectangleF(Me.Width / 2, 0, 20, 2)
display.FillRectangle(New Drawing.Drawing2D.HatchBrush(Drawing2D.HatchStyle.NarrowVertical, Me.ForeColor), myrect)

5) Finally, make sure you also handle the Resize event of your CoolSplitter
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.Invalidate() 'repaint control upon resize
End Sub
===================================================

Customizing the CoolSplitter (making it cooler)

=============================================

You can design the control in such a way that it allows users of your CoolSplitter to customize it a bit using the Property sheet. For instance, you might want fade colors and handle width to be customizable. The example below customizes the splitter handle background color


Public Property HandleColor() As System.Drawing.Color
Get
Return MyBase.ForeColor
End Get Set(ByVal Value As System.Drawing.Color)
MyBase.ForeColor = Value
End Set End Property
I hope this was a useful article. If you find any inconsistencies, or ambiguities, please contact me. If you have better solutions and would like to share with me, I will be delighted to learn about it.

Enjoy!
>

Tuesday, December 13, 2005

ReUsing DataTable with DataGrid


Language: VB.NET Version 1.11
Task:Create a tool like SQL-Query analyzer that returns result in a grid.
Problem: The data grid does not always display data!
ds.tables("searchResults").clear()
'Custom function that uses a SQLDataAdapter to fill the datatable with results of the query
fillBrowseSet(Me.query.Text.Trim, searchDT)
datagrid1.datasource = ds.tables("searchResults")
This works fine the first time. DataTable is filled and datagrid1 displays the result. The following request display a blank grid with no data, but correct column


Solution 1
Replace, ds.tables("searchResults").clear() with
ds.tables("searchResults").reset()
Then, bind the datagrid with the DataTable.

Problem with solution 1: If underlying schema of the datatable keeps changing, the data may appear, but all column may not appear correctly. This is usually due to the underlying contraint collection and the primary key collection bindings.

Explaination:
datagrid1.datasource = ds.tables("searchResults") AND datagrid1.datasource = ds.tables("searchResults").DefaulView

Both are effectively the same statements. datagrid1.datasource = ds.tables("searchResults") implicitly uses the dataview generated for the datatable, and datagrid1.datasource = ds.tables("searchResults").DefaulView explicitly points to the dataview to bind. The point is, DataSource property of the datagrid uses a DataView object to establish mapping on the datagrid column(s) with columns and data stored in the DataTable object.

The DefaultView property of the DataTable is a ReadOnly property that points to an immutable object. Every DataTable object has exactly one DataView object created for it. This DataView object is created during the construction of the DataTable object. This DataView object is therefore based on the underlying schema of the DataTable object at that time. The problem is, when the underlying schema of the DataTable changes, the associated DataView object is not automatically notified of the change, and is not re-Synchronized. So, the result is a disconnected DataView that is unable to provide a current binding to the DataGrid object.

You can test these findings using the debugger and checking the
TableName and Count properties of both the DataView and DataTable. You will notice, the two will contain the same values initially. The defaul DataView object will be reset upon disconnect and display a Count of 0 (zero).


My Solution
'Eliminate the use of a large and bulky DataSet object.
Private searchDT As DataTable
Private searchView As New DataView

searchDT = New DataTable("searchResult")
searchView.AllowDelete = False
searchView.AllowEdit = False
searchView.AllowNew = False

searchDT.Reset()
'The DataView object being used is no longer immutable, and can be manipulated
If Not searchView.Table Is Nothing Then
searchView.Table = Nothing
End If
fillBrowseSet(Me.query.Text.Trim, searchDT, False)
'Attach the dataview to refreshed DataTable object.
'This refreshes the DataVie
w
searchView.Table = searchDT
Me.resultGrid.SetDataBinding(searchView, "")

Advantages to this Technique:
1) We do not find the need to create a new DataView object for every new schema of DataTable
2) We avoid the use of a bulky DataSet object, and minimize cost associate with processing and boxing/un-boxing DataSet object. An independant DataTable object is enough for our purposes
3) We have control of the DataView object contained by the DataTable. searchView.Table = searchDT sets the new dataview object accessible by DefaultView property of DataTable