Turn an Enum into a list in VB.Net with optional CSLA#
From time to time you might have an enum that you want to databind to something as if it were a list, so I wrote some classes that turn an Enum into a list that you can databind. 

I created ways to do this in CSLA and also w/o CSLA.  I made the non-CSLA versions 1 work so that you can either use a sub class, or just use generics when defining the type of your list.  You can do the same with the CSLA versions if you want by changing some of the generics, but I didn't bother.

'*** csla
Dim cslaList As MyTestTypeList = MyTestTypeList.GetList

'*** non-csla with inherited subclass and without
Dim list As New MyTestTypeList2
Dim list2 As New EnumList2(Of MyTestType)


'*** enum we are using
Public Enum MyTestType
something = 1
here = 2
ok = 3
End Enum

'*** csla
<Serializable()> _
Public Class MyTestTypeList
Inherits EnumList(Of mytesttype, MyTestTypeList)

End Class
<Serializable()> _
Public Class EnumList(Of T As Structure, R As EnumList(Of T, R))
Inherits Csla.NameValueListBase(Of String, Integer)

Public Shared Function GetList() As R
Return Csla.DataPortal.Fetch(Of R)()
End Function

Protected Sub New()
' require use of factory method
End Sub

<Csla.RunLocal()> _
Public Overloads Sub DataPortal_Fetch() 'ByVal criteria As Object)
Me.IsReadOnly = False
For Each item As T In [Enum].GetValues(GetType(T))
Dim name As String = [Enum].GetName(GetType(T), item)
Add(New Csla.NameValueListBase(Of String, Integer).NameValuePair(name, [Enum].Parse(GetType(T), name)))
Next
Me.IsReadOnly = True
End Sub
End Class

'*** non-csla
Public Class MyTestTypeList2
Inherits EnumList2(Of MyTestType)

End Class

Public Class EnumList2(Of T As Structure)
Inherits List(Of EnumListItem)

Public Structure EnumListItem
Dim Name As String
Dim Value As Integer
Public Sub New(ByVal name As String, ByVal value As Integer)
Me.Name = name
Me.Value = value
End Sub
End Structure

Public Sub New()
For Each item As T In [Enum].GetValues(GetType(T))
Dim name As String = [Enum].GetName(GetType(T), item)
Add(New EnumListItem(name, [Enum].Parse(GetType(T), name)))
Next
End Sub

End Class


Categories: Programming | .Net | VB.Net
Friday, November 27, 2009 3:16:10 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Validating Enum Values#

You were a good developer and created an enum to represent the integer values that are being passed into your method.

It makes life easy for everyone.  Good job.

But now you realize that ANY integer can be passed into your function, even though your type only defines a handful of values.

Well, you need to validate the enum values that are coming into your method.

This can be done quickly with the following code snippet:

If Not [Enum].IsDefined(localId.GetType, localId) Then
    Throw New System.ComponentModel.InvalidEnumArgumentException("Invalid local value.")
End If

In this example localId is the variable name of type LocalType.

Categories: Programming | .Net | VB.Net
Thursday, July 24, 2008 1:55:29 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Using My.Settings on a referenced project#

I recently ran into some seemingly strange behavior as I was testing a couple windows services I had written.

In my case, I had a test harness program that was referencing the service (an exe) but this could also apply to references to dlls if you are using the projects application settings (My.Settings.Whatever in VB.Net).

After figuring it out, it all makes sense.

When you create an application setting by providing a value in the project's "Settings" tab, the value is written out into a special <applicationSettings> block in your config file.

But, in order to make those values accessible via a strongly typed/intellisense method, a class is created to wrap those values.  The class is in the Settings.vb file that is generated when you first add an application setting to your project.

But there is one more interesting thing to note:  If the settings class doesn't find the item it expects in the config file, it will return the last supplied value by default. 

So what this means is that if create an application setting for XYZ for the value "123" and then change the app.config file directly to change the "123" to "abc", then "abc" will be returned when you run the program.  However, if you were to then alter the config file to remove or rename the XYZ item, then your application would return "123" again when it ran.

Also, if you directly modify the config file, and then try to edit the projects applications settings, it will alert you to the fact that some values have changed, and ask if you want to use the updated values from the config file.  If you say yes, it will overwrite the Settings.vb file to use the new values that you had supplied in the config file.

So, I was referencing a project that used these settings, but when I would update the config file, those updated settings were not seen.  All I had to do was go into the project settings tab, allow it to refresh the Settings.vb file, and rebuild the project.

 

Categories: Programming | .Net | .Net Framework | VB.Net
Wednesday, August 22, 2007 8:07:09 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Webservices Compression#
Categories: Programming | .Net | .Net Framework | VB.Net | WebServices
Wednesday, May 02, 2007 3:34:54 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

TypeOf VB.NET vs C##

If you are Microsoft, why do you create a function "TypeOf" that has totally differnet applications in VB and C#?

Typeof in C# is like GetType in VB, where VB uses TypeOf to see if 2 types are the same or check for interface implementation.

Kinda dumb.

Categories: Programming | .Net | C# | VB.Net
Friday, April 06, 2007 8:59:58 AM (Central Daylight Time, UTC-05:00) #    Comments [3]  | 

 

VB Keyboard Shortcut Poster#

Shows all the vs.net ide shortcuts for vb.net.

Categories: Programming | .Net | VB.Net
Sunday, February 04, 2007 11:15:33 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Printing Vb.Net Forms with PrintForm Component#

Microsoft has released their first 3 Power Packs for Visual Basic 2005, which are "free Add-Ins, Controls, Components, and Tools for you to use with Visual Basic 2005 to make developing great applications even easier."

1 of the first 3 is the Microsoft PrintForm Component 1.0 , which gives you the ability to easily print a form.

I could have really used this on my last project, where I manually wrote the code to do just that.

Categories: Programming | .Net | VB.Net | VS.Net
Monday, October 09, 2006 2:58:15 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Convert a String to a Byte Array in VB.Net#

I had a snippet on my site for converting a byte array to a string, but I didn't have anything for going the other way.

This function should do the trick.

Public Shared Function StringByByteArray(ByVal s As String) As Byte()
    Return System.Text.Encoding.UTF8.GetBytes(s)
End Function


Categories: Programming | .Net | VB.Net
Wednesday, October 04, 2006 3:44:23 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VS.Net Macro to Narrow VB.Net Method Signatures and Function Calls#

Lately I have been doing some refactoring of code as I go through it.

Trying to name variables correctly, breaking up long methods, trying to adhere to some coding standards.

One way that I have been employing to clean up code is to convert very long method signatures, or calls to methods with many parameters from LONG single line entities to shorter multi-line blocks.

This is simple, but tedious.  So I wrote a VS.Net macro to do it for me.

Simply copy and paste the macro code (paste into wordpad first to get rid of the missing newline problem) at the bottom of this article into a macro.  Then all you have to do is highlight the entire row you want to "narrow", and run the macro.  You can always Cntl+z out of it if you want to undo the changes.

The results are good!  The following are examples of a long method signature, and a call to a method with a lot of arguments, and then the refactored results.

'*** Long method signature
Public Function ActivitySave(ByVal Activity As MyNamespace.Business.Equipment.Activity, ByVal StartTime As DateTime, ByVal EndTime As DateTime, ByVal StatusOverride As System.Nullable(Of MyNamespace.Business.Data.Criteria.Equipment.ActivityStatusEnum), ByVal Clerk As Integer) As Integer

'*** long method call
ActivityID = MainActivity.ActivitySave(Activity.ActivityID, Activity.Status, Activity.PurposeNotes, Activity.JobIndex, Activity.CategoryID, Activity.RequestedStartDate, Activity.RequestedEndDate, Activity.EquipmentID, Activity.PlanStartDate, Activity.PlanEndDate, Activity.ActualStartDate, Activity.ActualEndDate, Activity.DiscountScheduleID, Activity.DiscountOffset, Activity.CodeID, Activity.RentalRate, Activity.RowVersion, Clerk)

Here is the result of the refactoring:

'*** Refactored long method signature
Public Function ActivitySave(ByVal Activity As MyNamespace.Business.Equipment.Activity, _
ByVal StartTime As DateTime, _
ByVal EndTime As DateTime, _
ByVal StatusOverride As System.Nullable(Of MyNamespace.Business.Data.Criteria.Equipment.ActivityStatusEnum), _
ByVal Clerk As Integer) As Integer

'*** Refactored long call
ActivityID = MainActivity.ActivitySave(Activity.ActivityID, _
Activity.Status, _
Activity.PurposeNotes, _
Activity.JobIndex, _
Activity.CategoryID, _
Activity.RequestedStartDate, _
Activity.RequestedEndDate, _
Activity.EquipmentID, _
Activity.PlanStartDate, _
Activity.PlanEndDate, _
Activity.ActualStartDate, _
Activity.ActualEndDate, _
Activity.DiscountScheduleID, _
Activity.DiscountOffset, _
Activity.CodeID, _
Activity.RentalRate, _
Activity.RowVersion, _
Clerk)

 

Here is the macro.

 Public Sub NarrowMethodsAndCalls()
'Create an Undo context object so all the changes can be
'undone by CTRL+Z
Dim oUnDo As UndoContext = DTE.UndoContext

'Supress the User Interface. This will make it run faster
'and make all the changes appear once
DTE.SuppressUI = True
Try


Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
Dim sOrigText As String = oTextSelection.Text

Dim RegExp As New System.Text.RegularExpressions.Regex("([ .=_a-zA-Z0-9]*)\(")
Dim Match As System.Text.RegularExpressions.Match = RegExp.Match(sOrigText)
If Match.Success Then
Dim sMethod As String = Match.ToString
Dim sParametersAndReturn() As String = sOrigText.Replace(sMethod, "").Split(",")
Dim sFirstLineWhiteSpace As String
Dim sb As New System.Text.StringBuilder
sb.Append(" ", Trim(sMethod).Length)
sFirstLineWhiteSpace = sb.ToString

'*** redo the first line
oTextSelection.Text = sMethod & sParametersAndReturn(0) & ", _"
oTextSelection.NewLine()
oTextSelection.Text = sFirstLineWhiteSpace

For i As Integer = 1 To sParametersAndReturn.Length - 2
oTextSelection.Text = Trim(sParametersAndReturn(i)) & ", _"
oTextSelection.NewLine()
Next
oTextSelection.Text = Trim(sParametersAndReturn(sParametersAndReturn.Length - 1))
oTextSelection.NewLine()



Else
MsgBox("failed to find function regexp match")
End If
Catch ex As Exception
MsgBox("Error: " & ex.ToString)
Finally

'If an error occured, then need to make sure that the undo context is cleaned up.
'Otherwise, the editor can be left in a perpetual undo context
If oUnDo.IsOpen Then
oUnDo.Close()
End If

DTE.SuppressUI = False
End Try

End Sub
Categories: .Net | VB.Net | VS.Net | Macros
Wednesday, September 27, 2006 10:52:05 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Checking an objects type or implemented interfaces#

A common thing people might want to do is check if a object is a certain type, or inherits a type, or implements a type.

This can be done in VB.Net with the following code:

TypeOf someObject Is ClassName

This works for inheritance heirarchy as well as checking for interface implementation.

Here is a sample app showing it in practice.

imports Microsoft.VisualBasic
imports System
Imports System.Collections.Generic

public module MyModule
    sub Main
dim o as new subclass
        WL(typeof o is subclass)
        WL(typeof o is baseclass)
        WL(typeof o is IWhatever)
        RL()
    end sub

    #region "Helper methods"

    sub WL(text as object)
        Console.WriteLine(text)
    end sub

    sub WL(text as object, paramarray args as object())
        Console.WriteLine(text.ToString(), args)
    end sub
        
    sub RL()
        Console.ReadLine()
    end sub
    
    sub Break()
        System.Diagnostics.Debugger.Break()
    end sub

#end region

end module


public interface IWhatever
end interface
public class BaseClass

end class

public class SubClass
inherits BaseClass
implements IWhatever

end class
Categories: Programming | .Net | VB.Net
Wednesday, September 06, 2006 4:35:02 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VS.Net Macro for Generating Simple and CSLA Property Accessors#

Here are a few macros I wrote to generate property accessors from your class level variables.

These Macros are absolutely not an example of great coding.  They are really pretty crappy, but they do the job, so as I kept tweaking them I never went back to clean up the code or look into more elegant ways to accomplish this stuff.

Some notes about these macros:

1) dasBlog's code display tools somehow screws up the LFs, so if you cut and paste this code you might want to first paste it into Word, or WordPad.

2) These macros need some space between your last bit of code and the end of your class.  In other words, the line directly above "End Class" can't have code in it.  Fixing this bug wouldn't be a big deal but I haven't done it yet.

3) These macros will allow formatting of your variables/accessors in any of the following ways:

private csClassLevelString as String '*** property name "ClassLevelString"
private mModuleLevelInt as Integer '*** property name "ModuleLevelInt"
private _SomeObject as Object '*** property name "SomeObject"
private camelCaseBoolean as Boolean '*** WON'T work: property will be named "CaseBoolean"

4) To use these macros, simply declare your class level (instance) variables.  Then with your mouse, highlight the ones you want to create property accessors for.  You need to highlight the entire definition from "private" to data type, and of course you can highlight a bunch at 1 time.  i.e. I could highlight the entire code block above and it would produce 4 property accessors.

5) Again... this code... well it kinda sucks.  So if you are looking for a lesson on producing good code, avert your eyes, but the output is good.

 

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics

Public Module Module1

    Public Sub AddClassProperties()
        Call AddClassProperties(False)
    End Sub
    Public Sub AddCslaProperties()
        Call AddClassProperties(True)
    End Sub

    ' highlight the private properties
    Private Sub AddClassProperties(ByVal useCsla As Boolean)

        Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
        Dim iLinesSelected = oTextSelection.TextRanges.Count
        Dim colPropertyList As New Collection()
        Dim iIndex As Integer
        Dim oStart As EditPoint = oTextSelection.TopPoint.CreateEditPoint()
        Dim oEnd As TextPoint = oTextSelection.BottomPoint

        'Create an Undo context object so all the changes can be
        'undone by CTRL+Z
        Dim oUnDo As UndoContext = DTE.UndoContext

        'Supress the User Interface. This will make it run faster
        'and make all the changes appear once
        DTE.SuppressUI = True

        Try

            oUnDo.Open("Comment Line")

            Dim sProperty As String
            Dim sLineOfText As String

            Do While (oStart.LessThan(oEnd))

                sLineOfText = oStart.GetText(oStart.LineLength).Trim
                '*** do some kind of simple check to make sure that this line
                '*** isn't blank and isn't some other kind of code or comment
                If (sLineOfText.IndexOf(" As ") >= 0 And ( _
                    (sLineOfText.IndexOf("Public ") >= 0) Or _
                    (sLineOfText.IndexOf("Private ") >= 0) Or _
                    (sLineOfText.IndexOf("Dim ") >= 0) Or _
                    (sLineOfText.IndexOf("Protected ") >= 0) Or _
                    (sLineOfText.IndexOf("Friend ") >= 0) Or _
                    (sLineOfText.IndexOf("ReDim ") >= 0) Or _
                    (sLineOfText.IndexOf("Shared ") >= 0) Or _
                    (sLineOfText.IndexOf("Static ") >= 0) _
                    )) Then

                    sProperty = oStart.GetText(oStart.LineLength).Trim.Replace(" New ", " ").Replace("()", "")

                    colPropertyList.Add(sProperty)
                End If

                oStart.LineDown()
                oStart.StartOfLine()

            Loop

            If colPropertyList.Count > 0 Then

                For Each sProperty In colPropertyList
                    Call InsertProperty(sProperty, useCsla)
                Next

            Else
                MsgBox("You must select the class properties")
            End If

        Catch ex As System.Exception

            Debug.WriteLine(ex)
            If MsgBoxResult.Yes = MsgBox("Error: " & ex.ToString & vbCrLf & "Undo Changes?", MsgBoxStyle.YesNo) Then
                oUnDo.SetAborted()
            End If

            Return
        Finally

            'If an error occured, then need to make sure that the undo context is cleaned up.
            'Otherwise, the editor can be left in a perpetual undo context
            If oUnDo.IsOpen Then
                oUnDo.Close()
            End If

            DTE.SuppressUI = False
        End Try


    End Sub

    Private Sub InsertProperty(ByVal sProp As String, Optional ByVal UseCsla As Boolean = False)
        Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
        Dim sMember As String = sProp.Substring(sProp.IndexOf(" ")).Trim
        Dim sDataType As String
        Dim sName As String
        Dim i As Integer
        Dim iAscVal As Integer

        i = sMember.IndexOf("(")
        If Not i = -1 Then
            sMember = sMember.Substring(0, i)
        End If

        i = sMember.IndexOf("=")
        If Not i = -1 Then
            sMember = sMember.Substring(0, i)
        End If

        sDataType = sMember.Substring(sMember.IndexOf(" As ") + 1)

        For i = 0 To sMember.Length - 1
            'iAscVal = Asc(Mid(sName, i, 1))
            iAscVal = Asc(sMember.Chars(i))
            If iAscVal > 64 And iAscVal < 91 Then
                sName = sMember.Substring(i)
                Exit For
            End If
        Next i

        sName = sName.Substring(0, sName.IndexOf(" As ") + 1).Trim

        If sName.Length = 0 Then
            MsgBox("Unable to process the class property: " & sMember & ".  This is usually caused by an incorrect naming convention (e.g. not cxName)")
            Return
        End If

        sMember = sMember.Substring(0, sMember.Length - sDataType.Length).Trim

        With oTextSelection
            Dim pt As TextPoint = .ActivePoint.CodeElement(vsCMElement.vsCMElementClass).GetEndPoint(vsCMPart.vsCMPartWhole)
            If pt Is Nothing Then
                pt = .ActivePoint.CodeElement(vsCMElement.vsCMElementStruct).GetEndPoint(vsCMPart.vsCMPartWhole)
            End If
            .MoveToPoint(pt)
            .LineUp()
            .EndOfLine()

            .Text = "Public Property " & sName & "() " & sDataType
            .NewLine()
            If UseCsla Then
                .Text = "CanReadProperty(True)"
                .NewLine()
            End If
            .Text = "Return " & sMember
            .StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
            .StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, True)
            .Copy()
            .LineDown(False, 3)
            DTE.ExecuteCommand("Edit.Paste")
            If UseCsla Then
                .Text = "CanWriteProperty(True)"
                .NewLine()
                .Text = "If Me." & sMember & " <> Value then"
                .NewLine()
            End If
            .Text = "Me." & sMember & " = Value"
            If UseCsla Then
                .NewLine()
                .Text = "PropertyHasChanged()"
            End If
            .LineDown(False, 2)
            If UseCsla Then
                .LineDown(False, 1)

            End If
            .NewLine(2)

        End With

    End Sub


End Module

 

 

Categories: Code | Programming | .Net | VB.Net
Thursday, August 03, 2006 7:51:08 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Validating XML document against an XML Schema with VB.Net#

It seems like validating an XML document against a schema would be a pretty simple thing to do in the .Net framework, seeing as how they have such deep support for dealing with XML.

But as of yet, I haven't found a simple way to do it.

Here is the code I have been using to validate XML against an XML Schema.

Imports System.IO
Imports System.Xml
Imports System.Xml.Schema


Private schemaValidation As New ValidationEventHandler(AddressOf ValidationHandler)

Private Function ValidateXml(ByVal xmlFileName As String, ByVal xmlSchemaName As String) As Boolean
Using myFile As New FileStream(xmlFileName, FileMode.Open, FileAccess.Read, FileShare.None)
Dim xDoc As New Xml.XmlDocument()
xDoc.Load(myFile)
xDoc.Schemas.Add(GetSchema(xmlSchemaName))
Try
xDoc.Validate(schemaValidation)
Return True
Catch ex As XmlSchemaValidationException
Console.Write(ex.ToString)
Return False
Catch ex As XmlSchemaException
Console.Write(ex.ToString)
Return False
Catch ex As Exception
Console.Write(ex.ToString)
Return False
End Try
End Using
End Function

Private Function GetSchema(ByVal filePath As String) As XmlSchema
Dim schema As XmlSchema
Using s As New System.IO.FileStream(filePath, FileMode.Open)
Using reader As New StreamReader(s)
schema = XmlSchema.Read(reader, Nothing)
End Using
End Using
Return schema
End Function

Private Sub ValidationHandler(ByVal sender As Object, ByVal e As System.Xml.Schema.ValidationEventArgs)
Throw e.Exception
End Sub
 
Categories: Programming | .Net | .Net Framework | VB.Net | XML
Saturday, July 29, 2006 4:35:25 PM (Central Daylight Time, UTC-05:00) #    Comments [2]  | 

 

Sorting a generic List(Of T) using IComparable(Of T) #

List(Of T) supports sorting through it's Sort method.  When you call Sort it will use the default comparer for the items it contans.  So if you have a custom class in there, you need to implement IComparable or IComparable(Of T). 

Here is some code that shows how to do this.  This code sorts lowest to highest.

    Public Function CompareTo(ByVal other As CustomClass) As Integer Implements System.IComparable(Of CustomClass).CompareTo
Dim myscore As Integer = Me.SomeValue
Dim otherscore As Integer = other.SomeValue
If myscore > otherscore Then
Return 1
ElseIf myscore = otherscore Then
Return 0
Else
Return -1
End If
End Function
Categories: Programming | .Net | VB.Net
Sunday, July 16, 2006 3:15:15 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Printing a VB.Net Form#

I found this useful code at VB-Helper.com

 

#Region "Print"
    Private Declare Auto Function BitBlt Lib "gdi32.dll" (ByVal _
    hdcDest As IntPtr, ByVal nXDest As Integer, ByVal _
    nYDest As Integer, ByVal nWidth As Integer, ByVal _
    nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc _
    As Integer, ByVal nYSrc As Integer, ByVal dwRop As _
    System.Int32) As Boolean
    Private Const SRCCOPY As Integer = &HCC0020

    ' Variables used to print.
    Private m_PrintBitmap As Bitmap
    Private WithEvents m_PrintDocument As Printing.PrintDocument

    Private Sub PrintForm()
        ' Copy the form's image into a bitmap.
        m_PrintBitmap = GetFormImage()

        ' Make a PrintDocument and print.
        MsgBox(m_PrintDocument.PrinterSettings.PrinterName)
        m_PrintDocument = New PrintDocument
        m_PrintDocument.Print()
    End Sub

    Private Function GetFormImage() As Bitmap
        ' Get this form's Graphics object.
        Dim me_gr As Graphics = Me.CreateGraphics

        ' Make a Bitmap to hold the image.
        Dim bm As New Bitmap(Me.ClientSize.Width, _
            Me.ClientSize.Height, me_gr)
        Dim bm_gr As Graphics = Graphics.FromImage(bm)
        Dim bm_hdc As IntPtr = bm_gr.GetHdc

        ' Get the form's hDC. We must do this after 
        ' creating the new Bitmap, which uses me_gr.
        Dim me_hdc As IntPtr = me_gr.GetHdc

        ' BitBlt the form's image onto the Bitmap.
        BitBlt(bm_hdc, 0, 0, Me.ClientSize.Width, _
            Me.ClientSize.Height, _
            me_hdc, 0, 0, SRCCOPY)
        me_gr.ReleaseHdc(me_hdc)
        bm_gr.ReleaseHdc(bm_hdc)

        ' Return the result.
        Return bm
    End Function

    ' Print the form image.
    Private Sub m_PrintDocument_PrintPage(ByVal sender As _
        Object, ByVal e As _
        System.Drawing.Printing.PrintPageEventArgs) Handles _
        m_PrintDocument.PrintPage
        ' Draw the image centered.
        Dim x As Integer = e.MarginBounds.X + _
            (e.MarginBounds.Width - m_PrintBitmap.Width) \ 2
        Dim y As Integer = e.MarginBounds.Y + _
            (e.MarginBounds.Height - m_PrintBitmap.Height) \ 2
        e.Graphics.DrawImage(m_PrintBitmap, x, y)

        ' There's only one page.
        e.HasMorePages = False
    End Sub

#End Region
Categories: Programming | .Net | VB.Net
Wednesday, June 14, 2006 11:49:10 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VS2005 VB.Net Create Properties From Private Fields#

"Refactor!" has the ability to turn your fields into public accessible properties, but it kinda sucks because 1) you have to do it 1 at a time, and 2) the naming convetion is all wrong. 

For example if you have a private integer called myInt then your property will be MyInt1.  Not exaclty what I am looking for.

So I updated my 2002 macro for creating these properties.  It should allow you to follow a variety of naming conventions "m_XXX", "ciXXX", "strXXX" etc.

Just include the macro below, then just highlight your private fields, and run the macro.

   ' highlight the private properties
Public Sub AddClassProperties()

Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
Dim iLinesSelected = oTextSelection.TextRanges.Count
Dim colPropertyList As New Collection()
Dim iIndex As Integer
Dim oStart As EditPoint = oTextSelection.TopPoint.CreateEditPoint()
Dim oEnd As TextPoint = oTextSelection.BottomPoint

'Create an Undo context object so all the changes can be
'undone by CTRL+Z
Dim oUnDo As UndoContext = DTE.UndoContext

'Supress the User Interface. This will make it run faster
'and make all the changes appear once
DTE.SuppressUI = True

Try

oUnDo.Open("Comment Line")

Dim sProperty As String
Dim sLineOfText As String

Do While (oStart.LessThan(oEnd))

sLineOfText = oStart.GetText(oStart.LineLength).Trim
'*** do some kind of simple check to make sure that this line
'*** isn't blank and isn't some other kind of code or comment
If (sLineOfText.IndexOf(" As ") >= 0 And ( _
(sLineOfText.IndexOf("Public ") >= 0) Or _
(sLineOfText.IndexOf("Private ") >= 0) Or _
(sLineOfText.IndexOf("Dim ") >= 0) Or _
(sLineOfText.IndexOf("Protected ") >= 0) Or _
(sLineOfText.IndexOf("Friend ") >= 0) Or _
(sLineOfText.IndexOf("ReDim ") >= 0) Or _
(sLineOfText.IndexOf("Shared ") >= 0) Or _
(sLineOfText.IndexOf("Static ") >= 0) _
)) Then

sProperty = oStart.GetText(oStart.LineLength).Trim.Replace(" New ", " ").Replace("()", "")

colPropertyList.Add(sProperty)
End If

oStart.LineDown()
oStart.StartOfLine()

Loop

If colPropertyList.Count > 0 Then

For Each sProperty In colPropertyList
Call InsertProperty(sProperty)
Next

Else
MsgBox("You must select the class properties")
End If

Catch ex As System.Exception

Debug.WriteLine(ex)
If MsgBoxResult.Yes = MsgBox("Error: " & ex.ToString & vbCrLf & "Undo Changes?", MsgBoxStyle.YesNo) Then
oUnDo.SetAborted()
End If

Return
Finally

'If an error occured, then need to make sure that the undo context is cleaned up.
'Otherwise, the editor can be left in a perpetual undo context
If oUnDo.IsOpen Then
oUnDo.Close()
End If

DTE.SuppressUI = False
End Try


End Sub

Private Sub InsertProperty(ByVal sProp As String)
Dim oTextSelection As TextSelection = DTE.ActiveWindow.Selection
Dim sMember As String = sProp.Substring(sProp.IndexOf(" ")).Trim
Dim sDataType As String
Dim sName As String
Dim i As Integer
Dim iAscVal As Integer

i = sMember.IndexOf("(")
If Not i = -1 Then
sMember = sMember.Substring(0, i)
End If

i = sMember.IndexOf("=")
If Not i = -1 Then
sMember = sMember.Substring(0, i)
End If

sDataType = sMember.Substring(sMember.IndexOf(" As ") + 1)

For i = 0 To sMember.Length - 1
'iAscVal = Asc(Mid(sName, i, 1))
iAscVal = Asc(sMember.Chars(i))
If iAscVal > 64 And iAscVal < 91 Then
sName = sMember.Substring(i)
Exit For
End If
Next i

sName = sName.Substring(0, sName.IndexOf(" As ") + 1).Trim

If sName.Length = 0 Then
MsgBox("Unable to process the class property: " & sMember & ". This is usually caused by an incorrect naming convention (e.g. not cxName)")
Return
End If

sMember = sMember.Substring(0, sMember.Length - sDataType.Length).Trim

With oTextSelection
.MoveToPoint(.ActivePoint.CodeElement(vsCMElement.vsCMElementClass).GetEndPoint(vsCMPart.vsCMPartWhole))
.LineUp()
.EndOfLine()

.Text = "Public Property " & sName & "() " & sDataType
.NewLine()
.Text = "Return " & sMember
.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, True)
.Copy()
.LineDown(False, 3)
DTE.ExecuteCommand("Edit.Paste")
.Text = "Me." & sMember & " = Value"
.LineDown(False, 2)
.NewLine(2)

End With

End Sub

 

 

Update1: When using code that you cut and paste from here, you might need to first paste it into Word or Wordpad.

Update2: When using this macro, you need a space (new line) between the last private field variable and your end of class line.

Categories: .Net | VB.Net | VS.Net | Tools
Thursday, April 27, 2006 9:53:16 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

applicationSettings, appSettings. app.config, web.config and userSettings#

I have seen lots of posts from people in the newsgroups trying to figure out what the deal is with the new config options in .net 2.0.

The main reason people run into problems is due to MS making a number of changes, including changes between the beta and the RC product, resulting in different answers based on how early you encountered the issues.

You can still do things the way you did with .Net 1.x.

       <appSettings>

              <add key="MyKeyName" value="somevalue"/>

       </appSettings>

and then you can access it with:

Dim myvalue As String = System.Configuration.ConfigurationSettings.AppSettings.Item("ConnectionString")

However, if you try this, VS.Net will warn you:

This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.AppSettings

It is important to note that the "!" above indicates that the fully quallified class listed, is located in the System.Configuration assembly, which of course you have to add to your project. 

So unlike previous versions, you need to manually add a reference to System.Configuration in order to make this new call.

Now, .net 2.0 and vs.net 2005 have teamed up to offer a new option for storing user settings which may seem more complicated at first if you don't know exactly what you are doing.  In the project properties you can select a "Settings" tab where you are able to modify application settings, which are in turn stored in app.config.  These settings can either be "User" settings, or "Application" settings. 

Application settings are stored in the app.config (or web.config), and are read-only.  User settings have a default value that is stored in the app.config, but your application can overwrite these default values as needed, and the users settings will be stored in:

%USERPROFILE%\Local Settings\Application Data\<Company Name>\<appdomainname>_<eid>_<hash>\<verison>\user.config. (non roaming)

OR:

%USERPROFILE%\Application Data\<Company Name>\<appdomainname>_<eid>_<hash>\<verison>\user.config (roaming)


The other nice feature of the 2.0 way of accessing these settings is that the settings are saved as a specific type from a wide collection of available types (String, System.DateTime, System.Drawing.Color, System.Guid, Bool, StringCollection etc) and when you access them from your code they are available in intellisense.

This may seem like it isn't important, but it means you can't mistype a setting key, or accidently try an invalid cast from one of your settings.  Also, storing a collection was a real pain in 1.x.    Now you can create a collection quickly and it will be added to the user settings like this:

   <setting name="MyCol" serializeAs="Xml">

        <value>

            <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                xmlns:xsd="http://www.w3.org/2001/XMLSchema">

                <string>I am first</string>

                <string>second</string>

                <string>me third</string>

                <string>I am number four</string>

            </ArrayOfString>

        </value>

    </setting>

Pretty nice!

To access these properties you have 2 different ways depending on if you are using VB.Net or C#.

For VB.Net you use the "My" namespace and access it like this:

Dim mySetting As String = My.Settings.MySetting

For C# you access these settings through the "Properties" object

       string mySetting = Properties.Settings.Default.MyUserSetting;

That's it!

Categories: Programming | .Net | .Net Framework | C# | VB.Net
Wednesday, April 26, 2006 8:36:40 AM (Central Daylight Time, UTC-05:00) #    Comments [9]  | 

 

Byte Array To String#
Here is a very simple code snippet for converting a Byte Array to a String in VB.Net

Encoding.ASCII.GetString(bytes)



And here is a function for that uses it to convert a byte array to a string

    
Private Function streamToString(ByVal stream As System.IO.MemoryStream) As String
Dim o As New IO.StreamWriter(stream, System.Text.Encoding.Default)
Dim bytes(stream.Length - 1) As Byte
stream.Read(bytes, 0, stream.Length - 1)
Return Encoding.ASCII.GetString(bytes)
End Function

Categories: Programming | .Net | VB.Net | References
Thursday, April 20, 2006 9:58:39 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Implementing System.ICloneable and a Snippet#
This will provide the necessary functions to implement ICloneable as well as a type specific Clone method.
        
Public Function Clone() As ClassName
Dim bFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim stream As New System.IO.MemoryStream()
bFormatter.Serialize(stream, Me)
stream.Seek(0, System.IO.SeekOrigin.Begin)
Dim newClone As ClassName
newClone = CType(bFormatter.Deserialize(stream), ClassName)
Return newClone
End Function
Private Function ICloneableImplementation() As Object Implements System.ICloneable.Clone
Return Me.Clone
End Function


I wrapped this into a snippet that you can import into Visual Studio 2005.

Implement ICloneable.snippet (1.84 KB)


Categories: Programming | .Net | VB.Net | VS.Net | Tools
Thursday, April 20, 2006 9:00:40 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VS2005: C# Projects Get Reference Folder VB Doesn't#

In VS.Net 2003 projects had a little sub folder looking icon called References that you could quickly expance to see what assemblies are being referenced. 

In 2005, you have to open a projects page and navigate to the references tab, but only for VB.Net projects.  C# projects still get the nice shortcut.  Weird.

Categories: Programming | .Net | C# | VB.Net | VS.Net
Wednesday, April 19, 2006 3:51:13 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VB.Net: Passing Reference and Value Objects ByRef and ByVal#

Here is a little example of how vb.net deals with passing of objects ByRef and ByVal.  The short answer is that when you pass a reference type object (not a value type) byval, the object is copied back when the method if finished.  You never really have handle on the original object, which is evident by the fact that you can't set it = nothing.  However, if you pass ByRef then you can indeed set the object = nothing and it will remain null when you return to the calling function.

If you try the same thing, except using a value type structure, you will see almost the same behavior, except for the major differenct that if you pass a structure byval and then make a change to it, those changes will not be copied back to the calling function.

To see an example of this check out the code by clicking on the "More" button to read the full article. 
Categories: Programming | .Net | .Net Framework | VB.Net
Saturday, April 15, 2006 1:04:46 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Expert VB 2005 Business Objects eBook#

Here is the link to get the book in beta:
http://www.apress.com/book/bookDisplay.html?bID=10090

Expert VB 2005 Business Objects takes you from an opening discussion of logical architectures to detailed n-tier deployment options using the CSLA .NET Framework. Rockford provides enough understanding and detail for you to take this approach to your own projects, as many developers have already done.

Categories: Web Site Links | VB.Net
Monday, April 10, 2006 6:23:05 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Implementing ICloneable While Staying Type Safe#

I had always had issue with implementing ICloneable in the .Net Framework on my classes.  Implementing ICloneable requires that you return an Object, but a lot of time you don't want to return an Object type, you want to return a strongly typed object of type whatever.

Well, thanks to a tip I heard on .NetRocks from Rocky Lhotka, I have coded up an example of how you can a) Implement ICloneable, and b) return a strongly typed object from your Clone method.

Imports System

Public Class BusinessObject
Implements ICloneable
Private Function privateClone() As Object Implements ICloneable.Clone
Dim MyClone As Object = makeClone()
Return MyClone
End Function
Public Function Clone() As BusinessObject
Dim MyClone As BusinessObject = makeClone()
Return MyClone
End Function
Private Function makeClone() As BusinessObject
'*** do the clone here
End Function End Class

The trick is to implement ICloneable as a private function.  To be honest I have no idea why this works.  You would think that implementing the Clone method as a private function would mean that you couldn't access it, but as the code I wrote below shows, it does work.

imports Microsoft.VisualBasic
imports System
imports System.Collections

public module MyModule
    sub Main
RL()
        dim o as new BusinessObject
        WL("IClone " & o.Clone.IClone)
        WL("StandardClone " & o.Clone.StandardClone)
        dim i as System.ICloneable
        i = ctype(o, System.ICloneable)
        WL("IClone " & ctype(i.Clone,BusinessObject).IClone)
        WL("StandardClone " & ctype(i.Clone,BusinessObject).StandardClone)
        RL()
    end sub

    #region "Helper methods"

    sub WL(text as object)
        Console.WriteLine(text)
    end sub

    sub WL(text as object, paramarray args as object())
        Console.WriteLine(text.ToString(), args)
    end sub
        
    sub RL()
        Console.ReadLine()
    end sub
    
    sub Break()
        System.Diagnostics.Debugger.Break()
    end sub

#end region

end module


public Class BusinessObject
Implements System.ICloneable
    public IClone as string = ""
    public StandardClone as string = ""

Private Function privateClone() As Object Implements ICloneable.Clone
Dim MyClone As Object = makeClone()
        ctype(MyClone,BusinessObject).IClone = "true"
Return MyClone
End Function

Public Function Clone() As BusinessObject
Dim MyClone As BusinessObject = makeClone()
        MyClone.StandardClone = "true"
Return MyClone
End Function

Private Function makeClone() As BusinessObject
'*** do the clone here
        return new BusinessObject
End Function

End Class

I will have to get to the bottom of this private thing.  But at least this will work and do you want expect it to.

Update: I got some answers from a couple people online.
Alvin Bruney (
http://msmvps.com/blogs/Alvin/ ) suggested:

The modify tag, private, does not apply to the compiler. It is capable of
calling the method. The tag is applicable only to calling code.

This I knew, but I guess I was wondering why the compiler allows you to do this.  I guess it makes sense that the interface makes that method public, so public it is!   Case closed

Categories: .Net Framework | VB.Net | C#
Monday, April 10, 2006 9:10:44 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Indents Fixed! #

Well a little tweaking of the code that does the generation of the formatted code, and it now produces what I want:

        Public Shared Function AddTOQueryString(ByVal URL As String, ByVal Key As String, ByVal Value As String) As String
Dim RegExp As New System.Text.RegularExpressions.Regex(Key & "=.*?(&|$)")
Dim Match As System.Text.RegularExpressions.Match = RegExp.Match(URL)
If Match.Success Then
Return RegExp.Replace(URL, Key & "=" & Value & Match.Groups(1).ToString)
ElseIf URL.IndexOf("?") > 0 Then
Return URL & "&" & Key & "=" & Value
Else
Return URL & "?" & Key & "=" & Value
End If
End Function
        /// <summary>Gets or sets the RSS version to write.</summary>
        /// <exception cref="InvalidOperationException">Can't change version number after data has been written.</exception>
        public RssVersion Version
        {
            get { return rssVersion; }
            set
            {
                if(wroteStartDocument)
                    throw new InvalidOperationException("Can't change version number after data has been written.");
                else
                    rssVersion = value;
            }
        }

I am not sure that I like what it does with literal strings.  I will probably want to change that.

I am also now convinced that it will not due for formatting Javascript.  J# just doesn't share enough similar attributes.  This tool also doesn't support XML (or HTML), which would be a nice thing too.

This converter looks pretty sweet.  You can include your regions and it will let you keep them collapsed and then expand via javascript, excellent.

I could also just wire up the implementation I already have to deal with HTML and Javascript.

We will see... for now this will do.

Categories: Blogging | VB.Net
Sunday, April 09, 2006 12:51:00 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

HttpFilters, HttpModules, and HttpWastedABunchOfTime#

I was just about to make a post talking about the switch over to dasBlog.  I was going to talk about what I liked and didn't like and whatever, but mostly I was going to talk about the work I have been putting in on writing code that will filter out code and format it nicely.

I wrote and tested an HttpModule which loads a Reponse Filter that parses the Html looking for <code> tags and formats the code inside those nicely.

So I go to write my first post, and I am looking for a hyperlink button in the texteditor, but instead I see this icon that look like a C# file.  "No, I did not just waste all that time" I thought. 

public bool IsTimeWasted(String name){
    return true;
}

Public Function IsWasted(ByVal time As TimeSpent) As Boolean
  If time IsNot Nothing Then
    Return True
  Else
    Return False
  End If
End Function

var s;
s = 'asdf';
document.getElementById("asdf"); /* comment */

SELECT * FROM
ThingsToDo
WHERE
WastedTime <> 1
AND
Task = 'Writing HttpFilter'


0 rows returned

So you can see I basically wasted my time doing all that.

This tool doesn't provide an HTML code type, and I used J# in place of Javascript, but it works ok I guess.

The on thing it is really lacking is that it doesn't maintain indents!?!?  I manually restored the indents above, otherwise my vb code would look like this:

Public Function IsWasted(ByVal time As TimeSpent) As Boolean
If time IsNot Nothing Then
Return True
Else
Return False
End If
End Function

Which is weird, b/c it looks fine in the preview window... I will have to look into that.

 

 

Categories: Blogging | Code Link | VB.Net
Saturday, April 08, 2006 7:54:09 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

MSDN Chats#
I'm going to miss tomorrow's chat on VB.NET Threading, but the transcript will be here.
Categories: Programming | .Net | VB.Net
Monday, March 22, 2004 2:20:09 PM (Central Standard Time, UTC-06:00) #    Comments [0]  | 

 

Flash and VB#
Here are some articles about stuff with Flash and VB.
Article 1
Article 2

Article 2 is supposed to get rid of the right click that flash has.
Categories: Programming | .Net | VB.Net | Flash
Wednesday, October 15, 2003 12:02:38 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VS.NET Macro to Add Property Methods for Instance Variables#
Check out the colored HTML pages here.
Categories: Programming | .Net | VB.Net | VS.Net | Tools
Thursday, September 11, 2003 10:51:24 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VB.NET Syntax vs. C##
I found this page that really does a lot of comparison between VB.NET and C# syntax. I copied the page from http://www.internetwebfactory.com because the font they were using was terrible.
Categories: Programming | .Net | C# | VB.Net
Wednesday, July 02, 2003 11:31:33 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

VB.NET vs Nearly Every Other OOP Language#
Why does VB need to change stuff around?

If everyone on earth calls an abstract class an "abstract class", and they all use the keyword "abstract", why does VB change this to "MustInherit" ?

I think it's dumb.

VB.NET vs Everyone
 
Dumb dumb dumb.
Categories: Programming | .Net | VB.Net | References
Tuesday, June 03, 2003 7:01:54 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Convert C# to VB.NET to C##
Here are some pages that will convert C# code into VB.NET:
Asp Alliance
Kamalpatel.net

This page will go the other way, converting VB.NET code into C#:
Ellkay
Categories: Programming | C# | VB.Net | Tools | .Net
Thursday, May 29, 2003 11:30:52 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

More LDAP DirectoryEntry Issues...#
I should have known it wasn't over.

I am still making steady progress, but I am still finding stupid problems along the way.

Someone told me that they thought my assessment of my security problem was correct, that I need to get the ASP.NET worker thread to have higher access, not the default IIS user account, by using impersonation. I havn't found a way to do impersonation on just 1 page, so I think I will need to move the login page to a different directory and add another .config file.

Some of the goofy things I am finding are:
  1. When searching the directory for a user object, if you want to later call the .Invoke("SetPassword",agrs[]) then you need to specify the schema as "user" when doing the cnAD.Children.Find("CN=MyUser","user") method.
  2. If you try to invoke the ADSI "SetPassword" and you try to use the same password that the account already has, it will throw an error.
    I'm guessing this is because there is probably something indicating that the user must change the password or something, to get around this, I am first changing the password to a GUID, and then changing it again to what I want it to be.
    Call cnNewUser.Invoke("SetPassword", New Object() {New Guid().ToString()})
    Categories: Programming | .Net | .Net Framework | VB.Net
    Wednesday, May 28, 2003 2:50:06 PM (Central Daylight Time, UTC-05:00) #    Comments [3]  | 

     

    Adding User Through LDAP#
    I have been fighting with this damn thing for a long time now. The internet is covered with articles like this one from CodeProject.com, but no matter what I do, I can't seem to be able to set the password of a user that I create through LDAP. It doesn't really help that almost all the example code is C#, and I am working with VB.NET. The conversion isn't a big deal, but when you don't know what the problem is, I would rather see a VB.NET example somewhere.

    When I try to call the Invoke method, with "SetPassword" and a new password, I always get back "Logon failure: unknown user name or bad password".

    So frustrating....
    Categories: Code Links | Programming | .Net | .Net Framework | VB.Net
    Tuesday, May 27, 2003 2:27:14 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

     

    All content © 2010, Christopher May, Inc
    Open Job Positions
    On this page
    Google Ads
    This site
    Calendar
    <March 2010>
    SunMonTueWedThuFriSat
    28123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910
    Archives
    Sitemap
    Blogroll OPML
    Disclaimer

    Powered by: newtelligence dasBlog 2.3.9074.18820

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    Send mail to the author(s) E-mail

    Theme design by Jelle Druyts


    Pick a theme: