Archives

Archives / 2009 / September
  • Using a WPF StackPanel for Business Forms

    In WPF if you want to layout a typical business form like the one shown in Figure 1, most people would use a Grid control with rows and columns. However, you may also use a StackPanel control. While sometimes you might need the re-sizing capabilities of a Grid, you sometimes just need a fixed size. For a fixed-size form a StackPanel control can be a little easier and offers a little more flexibility.

    StackPanel Layout 

    Figure 1: A business form using a StackPanel

    Using a Grid
    If you were to layout the above form using a Grid control you might write code that looks like the following:

    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>
      <Label   Grid.Column="0" Grid.Row="0">FirstName</Label>
      <TextBox Grid.Column="1" Grid.Row="0" Name="txtFirst" />
      <Label   Grid.Column="0" Grid.Row="1">Last Name</Label>
      <TextBox Grid.Column="1" Grid.Row="1" Name="txtLast" />
      <Button  Grid.Column="1" Grid.Row="2" Name="btnClose">
        Close
      </Button>
    </Grid>

    In the above XAML code you need to assign the Grid.Row and a Grid.Column properties on each Label, TextBox and Button control. This is how the XAML knows where to place each control in the Grid.

    Using a StackPanel Control
    Now, let’s layout the same form using a series of StackPanel controls. Each StackPanel for each “row” will have the Orientation set to “Horizontal”. There will also be a Style setup for each Label to set the Width property to a specific amount so each text box will be aligned correctly. Below is what the form that uses the StackPanel looks like.

    <StackPanel>
      <StackPanel Orientation="Horizontal">
        <Label>First Name</Label>
        <TextBox Name="txtFirst"></TextBox>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <Label>Last Name</Label>
        <TextBox Name="txtLast"></TextBox>
      </StackPanel>
      <StackPanel Orientation="Horizontal">
        <Label></Label>
        <Button Name="btnClose">Close</Button>
      </StackPanel>
    </StackPanel>

    Now here are the styles that you add to the Window.Resources on this window to give the form its structure.

    <Window.Resources>
      <Style TargetType="Label">
        <Setter Property="Width" Value="100" />
      </Style>
      <Style TargetType="TextBox">
        <Setter Property="MinWidth" Value="160" />
      </Style>
    </Window.Resources>

    Now, there are advantages and disadvantages to using a Grid and to using a StackPanel. A Grid is great because the text box controls will automatically re-size as the user sizes the form. However, if you have several rows and you wish to insert a row in the middle, you need to renumber each row after the new row. Sometimes the VS.NET designer will renumber them for you, but sometimes it won’t. Or, if you wish to move an existing row below or above another, you will also be doing a lot of manual renumbering.

    Many business forms do not require re-sizing, so in this case a StackPanel works very well. Using styles gives you the same flexibility as the Grid column definitions, so this is very nice. Also, the ability to just move rows around without worrying about renumbering is a great benefit. However, you do lose the re-sizing capabilities, so this is a tradeoff.

    Summary
    As with most WPF applications, there are typically more ways than one to accomplish the same thing. This is probably the most frustrating part of learning WPF. Here I showed you a couple different ways to layout the same business form. Each method has its advantages and disadvantages, so it will be up to you to determine when to use each method.

    Read more...

  • Split Name into First and Last

    Not too long ago we received a text file of customer names. The problem with the file is it just had one field "Name". One of the requirements of our database application was to have a first name field and a last name field so our customer could search for their customers on either field. As a result we needed to take this text file and split out the data into the two fields from the one.

    As we looked into this file, we noticed that the data was in complete disarray! Some of the names were entered like "First Last", and some in the format "Last, First". So, we needed to perform a little string parsing to get the data into our database table. The following is a simplified version of the routine we wrote to attempt to handle each format and create a new Customer object that we could then use to populate our database table.

    First we needed to create a Customer class. We created an instance of this Customer class and passed in the "name" value read from the text file into the method of the Customer class named NameSplit().

    C#
    class Customer
    {
      public string FirstName { get; set; }
      public string LastName { get; set; }

      public void NameSplit(string name)
      {
        if(name.Length > 0)
        {
          // Check for a comma
          if(name.IndexOf(",") > 0)
          {
            LastName = name.Substring(0, name.IndexOf(",")).Trim();
            FirstName = name.Substring(name.IndexOf(",") + 1).Trim();
          }
          else if(name.IndexOf(" ") > 0)
          {
            FirstName = name.Substring(0, name.IndexOf(" ")).Trim();
            LastName = name.Substring(name.IndexOf(" ") + 1).Trim();
          }
        }
      }
    }


    Visual Basic
    Public Class Customer
      Private mFirstName As String
      Private mLastName As String

      Public Property FirstName() As String
        Get
          Return mFirstName
        End Get
        Set(ByVal Value As String)
          mFirstName = Value
        End Set
      End Property

      Public Property LastName() As String
        Get
          Return mLastName
        End Get
        Set(ByVal Value As String)
          mLastName = Value
        End Set
      End Property

      Public Sub NameSplit(ByVal name As String)
        If name.Length > 0 Then
          ' First check for a comma to see if they entered Last, First
          If name.IndexOf(",") > 0 Then
            mLastName = name.Substring(0, name.IndexOf(",")).Trim()
            mFirstName = name.Substring(name.IndexOf(",") + 1).Trim()
          ElseIf name.IndexOf(" ") > 0 Then
            mFirstName = name.Substring(0, name.LastIndexOf(" ")).Trim()
            mLastName = name.Substring(name.LastIndexOf(" ") + 1).Trim()
          End If
        End If
      End Sub
    End Class

    To test out this method, use the following code:

    C#
    private void TestCustomerSplit()
    {
      Customer cust;

      cust = new Customer();
      cust.NameSplit("Bruce Jones");
      MessageBox.Show(cust.FirstName + " " + cust.LastName);

      cust = new Customer();
      cust.NameSplit("Jones, Bruce");
      MessageBox.Show(cust.FirstName + " " + cust.LastName);
    }

    Visual Basic
    Private Sub TestCustomerSplit()
      Dim cust As Customer

      cust = New Customer()
      cust.NameSplit("Bruce Jones")
      MessageBox.Show(cust.FirstName & " " & cust.LastName)

      cust = New Customer()
      cust.NameSplit("Jones, Bruce")
      MessageBox.Show(cust.FirstName & " " & cust.LastName)
    End Sub

    Another way to accomplish this task would have been to use the Split() method of the String class. You can split a string on a specific character like a space or a comma. You then end up with an array of each name. I will leave that as an exercise for you to do! :)

    You just have to love the string parsing capabilities of .NET! Just a little bit of code was all it took to make this job of turning different formats into something that was much easier to work with.

    Good Luck With Your Coding,
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

    Read more...

  • Date Handling Tip Part 2: Get the Month Name as Extension Method

    After my last post on the GetMonthName, I had a question on how to add this method to the DateTime class as an Extension method. I thought this would make a good follow-up, so here is how you can accomplish this.

    First, let's do the C# extension method. Add a new class to your project. For this example, I called the class "MyExtensions". This class needs to be defined as a static class. Next add a public method called GetMonthName. This is a static method and accepts a DateTime object as a parameter. Remember that with Extension methods you need to use the keyword "this" in front of the parameter. Below is the C# example:

    public static class MyExtensions
    {
      public static string GetMonthName(this DateTime dateValue)
      {
        DateTimeFormatInfo info = new DateTimeFormatInfo();

        return info.MonthNames[dateValue.Month - 1];
      }
    }


    To use this extension method you can write code like the following:

    DateTime value;

    value = DateTime.Now;

    MessageBox.Show(value.GetMonthName());

    Now, let's take a look at how to accomplish the same thing in Visual Basic. With Visual Basic there is no such thing as a Shared class, so instead you use a Module. So, we add a module to our project called "MyExtensions" to our project. You have to import the System.Runtime.CompilerServices namespace as we will be attaching an Attribute to our extension method. Below is what our new module now looks like.

    Imports System.Runtime.CompilerServices
    Imports System.Globalization

    Module MyExtensions
      <Extension()> _
      Public Function GetMonthName(ByVal dateValue As Date) As String
        Dim info As New DateTimeFormatInfo

        Return info.MonthNames(dateValue.Month - 1)
      End Function
    End Module

    Now, to use this new extension method simply write code like the following:

    Dim value As Date

    value = Now

    MessageBox.Show(value.GetMonthName())

    Good Luck With Your Coding,
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

    Read more...

  • Date Handling Tip: Get the Month Name

    There are a lot of great date handling methods attached to the DateTime class in .NET. However, if you wish to get information such as the current month name, you will not find it in this class. The reason is because .NET needs to take into account local culture and languages. Thus, methods that return something that is specific to a language or a culture are placed under the System.Globalization namespace. As an example, below is the code you would need to write to return the month name as a string in any language.

    VB.NET
    Imports System.Globalization

    Public Shared Function GetMonthName(ByVal dateValue As Date) As String
      Dim info As New DateTimeFormatInfo
      Dim names() As String

      names = info.MonthNames

      Return names(dateValue.Month - 1)
    End Function

    Here is the same code in C#:

    C#
    using System.Globalization;

    public static string GetMonthName(DateTime dateValue)
    {
      DateTimeFormatInfo info = new DateTimeFormatInfo();
      string[] names;

      names = info.MonthNames;

      return names[dateValue.Month - 1];
    }

    In the code above, you create an instance of the DateTimeFormatInfo class. This class is located in the System.Globalization namespace. It is this class that has properties for the month names, day names, abbreviated month names, the month separator character and other characteristics of dates that can change with local culture.

    You call the GetMonthName method presented above and pass in any valid date/time value and the month name for that date will be returned. For example, if you were to wrap the above method into a class called MyDates, then you would write code as shown below:

    MessageBox.Show(MyDates.GetMonthName(DateTime.Now));

    Now, of course, you do not need to wrap up the calls to the DateTimeFormatInfo as I did here. You can just use the properties and methods of the DateTimeFormatInfo class directly. I presented it as I did above for clarity. You can always just call any of the various properties and methods directly. For example, there is a GetMonthName() method that you can call and just pass in the month number.

    DateTimeFormatInfo info = new DateTimeFormatInfo();

    MessageBox.Show(info.GetMonthName(DateTime.Now.Month));

    You can also get any of the day names of the weeks by using the GetDayName() method.

    DateTimeFormatInfo info = new DateTimeFormatInfo();

    MessageBox.Show(info.GetDayName(0));

    There is much more to the DateTimeFormatInfo class than I presented here, so take some time and check out all the various methods and properties of this powerful class.

    Read more...

  • Check if String is All Lower or All Upper Case

    Funny how sometimes there are so many ways to accomplish the same thing. In a project last week I needed to check if a user entered a sentence in all lower (or could have been upper) case. So I immediately went to the most simple solution; using the ToLower() method on the string object and comparing the original string input to the lower version of the same sentence. The code is shown below.

    private bool IsAllLowerCase(string value)
    {
      return (value.Equals(value.ToLower()));
    }

    This is a simple method that should be fairly performant. I then started to think that I could also use a regular expression to do this as well. This is shown in the following code:

    using System.Text.RegularExpressions;

    private bool IsAllLowerCase(string value)
    {
      // Allow anything but upper case
      return new Regex(@"^([^A-Z])+$").IsMatch(value);
    }

    I have seen many fancy, complicated versions of this, but for this situation I wanted to allow any character, number or punctuation, I just do not want upper case characters. This small little Regular Expression does the job quite nicely.


    Here is the same code using the ToLower() method and regular expressions using Visual Basic.

    Private Function IsAllLowerCase( _
     ByVal value As String) As Boolean
       Return (value.Equals(value.ToLower()))
    End Function

    Imports System.Text.RegularExpressions

    Private Function IsAllLowerCase( _
     ByVal value As String) As Boolean
       Return New Regex("^([^A-Z])+$").IsMatch(value)
    End Function

    Of course, you can see that you can just flip this around to check to see if a string is all upper case too.

    Good Luck With Your Coding,
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

     

    Read more...

  • Using The ConnectionStringBuilder class

    Building a connection string from scratch can sometimes be a little daunting when you do not know the exact syntax. Of course, you can always visit www.connectionstrings.com and find some great help there. In lieu of this you can also use the ConnectionStringBuilder class. Each of the ADO.NET providers supplies a version of this class that will build a connection string for you. Below is an example of how to use this class.

    VB.NET
    Imports System.Data.SqlClient

    Private Sub CreateConnectionString()
      Dim builder As New SqlConnectionStringBuilder

      builder.DataSource = "(local)"
      builder.InitialCatalog = "Northwind"
      builder.UserID = "user1"
      builder.Password = "P@ssw0rd"

      MessageBox.Show(builder.ConnectionString)
    End Sub

    C#
    using System.Data.SqlClient;

    private void CreateConnectionString()
    {
      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

      builder.DataSource = "(local)";
      builder.InitialCatalog = "Northwind";
      builder.UserID = "user1";
      builder.Password = "P@ssw0rd";

      MessageBox.Show(builder.ConnectionString);
    }

    This is a pretty easy class to use. You can just fill in the basic information such as the DataSource, InitialCatalog, the UserId and Password and it will create a connection string for you. The output from the above code will be: "Data Source=(local);Initial Catalog=Northwind;User ID=user1;Password=p@ssword".

    To add on additional keywords for your connection string you may use the Add method. This method takes the keyword and the value and will add them in the appropriate format to your connection string.

    As mentioned, each ADO.NET data provider supplies one of these classes. For example, if you are using Oracle, you would use the System.Data.OracleClient namespace, then use the OracleConnectionStringBuilder.

    The ConnectionStringBuilder class allows you to parse the individual elements of a connection string and put them into the corresponding properties in the ConnectionStringBuilder. In the following example you take an existing connection string like the one shown in the code below and place it into the ConnectionString property of the ConnectionStringBuilder. The ConnectionStringBuilder will then break it into the appropriate properties.

    VB.NET
    Private Sub ParseConnectionString()
      Dim cnn As String
      Dim builder As New SqlConnectionStringBuilder

      cnn = "Server=Localhost;Initial Catalog=Northwind;User ID=user1;Password=P@ssw0rd"

      builder.ConnectionString = cnn

      MessageBox.Show(builder.DataSource)
      MessageBox.Show(builder.InitialCatalog)
      MessageBox.Show(builder.UserID)
    End Sub

    C#
    private void ParseConnectionString()
    {
      string cnn;
      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

      cnn = "Server=Localhost;Initial Catalog=Northwind;User ID=user1;Password=P@ssw0rd";

      builder.ConnectionString = cnn;

      Debug.WriteLine(builder.DataSource);
      Debug.WriteLine(builder.InitialCatalog);
      Debug.WriteLine(builder.UserID);
    }

    So the next time you have a connection string that you wish to extract the elements from, or you need to build a connection string, consider using the ConnectionStringBuilder class. I would not recommend using this in a production application as I can't imagine that the performance would be that great, but for figuring out a connection string, this works great.

    Good Luck With Your Coding,
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

    Read more...

  • Unit Testing in VS.NET 2008 - Live Meeting Recording

    Last night I did a live webcast for the Florida .NET User Groups (www.fladotnet.org) on Unit Testing in VS.NET 2008. If you are interested in viewing this Live Meeting seminar it has been recorded. Details are below:

    Subject: FlaDotNet Online: Build Unit Tests the Easy Way with VS.NET 2008
    Recording URL: https://www.livemeeting.com/cc/mvp/view
    Recording ID: NNRDN8
    Attendee Key: F8swp9,WR

     

     

    Enjoy!
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

     

    Read more...