C#: Calling a Constructor from Another Constructor in the Same Class


If you have a child class that extends or inherits from another class, you can ensure a specific constructor in the parent class is called by using the : base() syntax as shown below.

public class Parent
{
    public Parent()
    {
        // Empty constructor called by default        
    }

    public Parent(int value)
    {
        this.Value = value;       
    }
}

public class Child : Parent
{
    public Child(int value) : base(value)
    {
        // Using the base keyword and supplying the value
        // parameter, ensures that the second constructor
        // in the Parent class is called rather than
        // the first
    }
}

In the example above, when creating a new Child object, the second constructor in the Parent class will be called instead of the first. But, what if you want to call one constructor from another in the same class? Take the example below, where each constructor assigns a value to the DistanceTraveled variable.

public class Trip
{    
    public Trip(decimal distanceTraveled)
    {
        this.DistanceTraveled = distanceTraveled;   
    }

    public Trip(decimal travelTime, decimal velocity)
    {
        this.DistanceTraveled = travelTime * velocity;
    }
}

While this code works, you are updating the DistanceTraveled variable in two different places which is less than desirable from a maintenance perspective (understandably this is a trivial example but with little thought I’m sure you can think of a real world situation where this would this could cause a larger problem). It would be nice to be able to call the first constructor from the second, passing in the product of the two parameters. Using the base keyword won’t work in this situation as we want to call a constructor in the same class, not a parent class. It turns out that if we simply swap ‘base’ for ‘this’, our goal can be achieved.

public class Trip
{    
    public Trip(decimal distanceTraveled)
    {
        this.DistanceTraveled = distanceTraveled;
    }

    public Trip(decimal travelTime, decimal velocity) : this (travelTime * velocity)
    {
        // the DistanceTraveled variable is updated by a call to the first constructor
    }
}

C#: Compare Application Version Numbers


UPDATE: As discussed in the comments, 99% of the time using the System.Version class included in the .net Framework will suffice for comparing application version numbers. Documentation for this can be found here. The below post will help you if for some reason (ex. you use commas instead of periods to separate the version number) the System.Version class will not work

When incorporating an automatic update feature into an application, one of the things that you will need to do is compare the installed version number to the currently available version number. Given version numbers of the format ‘X.X.X.X’ I have seen some people suggest simply removing the periods, converting the string to an integer and doing a simple comparison of the integers. Such a solution works great if you have complete control over the format of the version number and you can ensure the number of digits per grouping stays the same. But, suppose you have the following two version numbers: 1.4.0 and 1.1.28. Following the logic explained above, you will be comparing the integers 140 and 1128 and the second version will be determined to be greater than the first, which is incorrect.

In order to alleviate this problem, I have created the following method below to correctly compare two version numbers. This method uses the SplitToList extension which takes a string, splits it based on a given string and then converts each element to the specified type. You can find a more detailed explanation and the code here.

public static int CompareVersionNumbers(string versionA, string versionB)
{           
    // Convert each version numbers string to a list of integers
    List<int> a = versionA.SplitToList<int>(".");
    List<int> b = versionB.SplitToList<int>(".");            
   
    // Ensure that each of the lists are the same length
    while(a.Count < b.Count) { a.Add(0); }
    while(b.Count < a.Count) { b.Add(0); }

    // Compare elements of each list
    for (int i = 0; i < a.Count; i++)
    {
        // If the element from list A is greater than B, 
        // versionA is greater than versionB and visa versa.
        // If they are equal, go to the next element.
        if (a[i] > b[i])
            return 1;
        else if (b[i] > a[i])
            return -1;
    }

    // If we reach this point, the versions are equal
    return 0;
}

Crystal Reports: Displaying a Check Mark for a Boolean Value


Crystal Reports gives you a few options of how to display a boolean value including Yes and No, Y and N, True and False, and 0 and 1. But, frequently I want to show a check mark for true values and the empty string for false values. This isn’t a difficult task, I just never remember the correct character codes.

To do this, either create a new formula field or enter the following formula in the Display String formula of the field and set the font property to Windings.

if {Table.Field} then
    Chr(252)
else
    ""

The above is illustrated in the Void column in the image below. When the check has been voided, a check mark appears in the Void column.

If you want to display a check box with a check mark for true and empty for false, use the following code.

if {Table.Field} then 
    Chr(254) 
else
    Chr(168)

C#: DataGridViewComboBoxColumn Displaying Different Values in Drop Down List


You can add a DataGridViewComboBoxColumn to the DataGridView to allow your users the ability to select from a list of items when editing the cell’s contents. I ran into a situation today where I needed to display a description of each item in the drop down list of the ComboBox but after the user selected an item, I only wanted the name of the item to be displayed and not the description as well. The following image shows an example of what I wanted; the drop down list shows a description of each animal but when selected, only the type of the animal is shown.

Unfortunately, the DataGridViewComboBoxColumn has a single DisplayMember property that lets you specify which property of the objects bound to the control is displayed to the user. So, to allow for the desired result, I needed to change the DisplayMember property when the drop down list is visible to show both the type and description and when the drop down list is not visible, to only show the type. The code below allows us to accomplish just this.

The form is setup with a DataGridView and two columns, if which the first is a ComboBoxColumn. I have a simple Animal class as defined below.

public class Animal
{
    public string Type { get; set; }
    public string Description { get; set; }

    public string TypeAndDescription { get { return Type + " - " + Description; } }
}

At the initialization if the form, we simply add a few Animal objects to the column’s Items collection and set the default DisplayMember to Type.

public Form1()
{
    InitializeComponent();

    this.clmAnimal.Items.Add(new Animal() { Type = "Dog", Description = "Fury animal that barks" });
    this.clmAnimal.Items.Add(new Animal() { Type = "Cat", Description = "Fury animal that meows" });
    this.clmAnimal.Items.Add(new Animal() { Type = "Mouse", Description = "Small rodent with a tail" });
    this.clmAnimal.Items.Add(new Animal() { Type = "Rabbit", Description = "Small with two large ears" });            

    this.clmAnimal.DisplayMember = "Type";
    this.clmAnimal.DropDownWidth = 180;
}

From the designer, there is no way to wire up the DataGridViewComboBoxColumn DropDown and DropDownClosed events. To do this, we need to handle the EditingControlShowing event of the DataGridView. This event fires when a control used for editing the value in the DataGridView is shown. This event will be fired when the user clicks on the cell to select an item from the ComboBox. Add the following code to this event.

private void dataGridViewAnimals_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    // Cast the editing control to a ComboBox
    ComboBox cmbBx = e.Control as ComboBox;

    // If the cast was successful, wire up the DropDown and DropDownClosed events
    if (cmbBx != null)
    {
        cmbBx.DropDown -= new EventHandler(ComboBoxCell_DropDown);
        cmbBx.DropDown += new EventHandler(ComboBoxCell_DropDown);

        cmbBx.DropDownClosed -= new EventHandler(ComboBoxCell_DropDownClosed);
        cmbBx.DropDownClosed += new EventHandler(ComboBoxCell_DropDownClosed);
    }
}

Then add the following code to handle the DropDown and DropDownClosed events.

private void ComboBoxCell_DropDown(object sender, EventArgs e)
{
    // When the drop down list appears, change the DisplayMember property of the ComboBox
    // to 'TypeAndDescription' to show the description
    DataGridViewComboBoxEditingControl cmbBx = sender as DataGridViewComboBoxEditingControl;
    if (cmbBx != null)
        cmbBx.DisplayMember = "TypeAndDescription";
}

private void ComboBoxCell_DropDownClosed(object sender, EventArgs e)
{
    // When the drop down list is closed, change the DisplayMember property of the ComboBox
    // back to 'Type' to hide the description
    DataGridViewComboBoxEditingControl cmbBx = sender as DataGridViewComboBoxEditingControl;
    if (cmbBx != null)
        cmbBx.DisplayMember = "Type";
}

The above code will allows us to display a different value when the ComboBox’s drop down list is displayed than what is displayed after the user selects an item from the list.

C#: String to Integer, Decimal, Float, or Any Type of Array or List


The string.Split method is a great tool that can be used when manipulating strings. But, this method simply returns an array of strings when frequently I need a collection returned in the type that the strings actually represent. To fix this you simply have to loop through each item in the string array and convert it to its representative type. For example, if you are reading in a comma delimited file of temperatures, you can split on the commas and then loop through the returned array, parsing each element and adding it to a new list, as follows:


string temperatures = "67.2,92.1,78.2,100.3,89.2";

string[] tempArray = temperatures.Split(',');

List<float> temps = new List<float>();
foreach (string temp in tempArray)
    temps.Add(float.Parse(temp));

While such a solution is common and quite acceptable, I wanted to make it simpler and reusable. To do such, I decided to implement the above logic in a generic extension method.


/// <summary>
/// Splits a string using the supplied separator and casts each element to the
/// indicated type.
/// </summary>
/// <typeparam name="T">The type of the List to return</typeparam>        
/// <param name="s">The string on which the operation will be performed.</param>
/// <param name="separator">An array of strings that delimit the substrings in this string, an empty
///     array that contains no delimiters, or null.</param>
/// <returns>A List of type T containing the elements formed after splitting the string using
/// the given separators.</returns>
public static List<T> SplitToList<T>(this string s, params string[] separator)
{
    return s.SplitToList<T>(StringSplitOptions.None, separator);
}

/// <summary>
/// Splits a string using the supplied separator and casts each element to the
/// indicated type.
/// </summary>
/// <typeparam name="T">The type of the List to return</typeparam>        
/// <param name="s">The string on which the operation will be performed.</param>
/// <param name="options">Specify System.StringSplitOptions.RemoveEmptyEntries to omit empty array
///     elements from the array returned, or System.StringSplitOptions.None to include
///     empty array elements in the array returned.</param>
/// <param name="separator">An array of strings that delimit the substrings in this string, an empty
///     array that contains no delimiters, or null.</param>
/// <returns>A List of type T containing the elements formed after splitting the string using
/// the given separators.</returns>
public static List<T> SplitToList<T>(this string s, StringSplitOptions options, params string[] separator)
{
    // Split the string based on the supplied separators
    string[] array = s.Split(separator, options);
    
    List<T> values = new List<T>();

    // Convert each element in the array to the indicated type
    foreach (string element in array)
        values.Add((T)Convert.ChangeType(element, typeof(T)));                

    return values;
}

Now our temperature example can be reduced to the following:


string temperatures = "67.2,92.1,78.2,100.3,89.2";
List<float> temps = temperatures.SplitToList<float>(",");

Below are some other examples of how this extension method could be used:

string s1 = "true-false-true-true-true-false";
List<bool> bools = s1.SplitToList<bool>("-");

string s2 = "a b c d e f g h i j";
List<char> chars = s2.SplitToList<char>(" ");

// Split on both commas and periods
string s3 = "1,3,4.5.7,1.4,6.7,8.2";
List<int> ints = s3.SplitToList<int>(",", ".");

C#: ListView – Dynamically Sizing Columns to Fill Whole Control


The DataGridView provides many options when it comes to defining the width of each column. My personal favorite is to set the AutoSizeMode property to Fill and then define a FillWeight for each column. Doing such will automatically resize each column according to its FillWeight property no matter how the user resizes the form. I was looking for such a property when using the ListView control in detail mode but apparently there is no such feature.

According to the MSDN documentation here, setting the column header Width property to -1 will automatically adjust the column width to the longest item in the column and setting the column header Width property to -2 will automatically adjust the width of the column to the size of the column heading. But, there is no Fill setting that will automatically adjust each column proportionality like is done in the DataGridView.

The simplest solution here is to just use a DataGridView and drop the ListView entirely, but in my situation, the ListView rendered the data much more to my liking that I could get the DataGridView to do. Given that no such solution was available, I decided to write one up myself using the ListView.SizeChanged event. The ListView.SizeChanged event is fired every time the size of the ListView changes, obviously, and thus with a bit of logic in this event we can programmatically emulate the auto sizing of the columns as done in the DataGridView.

Disclaimer: The best way to implement this is to create a custom control derived from the ListView class that contains the following logic. For simplicity, I have just used the stock ListView control and the SizeChanged event.

At design time when you define the ListView columns, enter the desired FillWeight of the column as an integer in the Tag property. Originally I tried just using the Width property but ran into problems recovering the correct value when the calculated width went to zero. If we set the FillWeight in the Tag property, it will stay constant for the life of the control (if you can ensure it isn’t changed at runtime). Again, ideally if you created a custom control, you could create a custom FillWeight property instead of using the Tag property,

Then, place the code that follows in the SizeChanged event. This code calculates the percentage of space each column should occupy and then sets the width of the column appropriately depending on the visible space the ListView control occupies. When resizing the ListView, this code is called multiple times. In an effort to reduce the number of calculations performed, we use the Resizing flag.


private bool Resizing = false;

private void ListView_SizeChanged(object sender, EventArgs e)
{
    // Don't allow overlapping of SizeChanged calls
    if (!Resizing)
    {
        // Set the resizing flag
        Resizing = true;

        ListView listView = sender as ListView;
        if (listView != null)
        {                               
            float totalColumnWidth = 0;

            // Get the sum of all column tags
            for (int i = 0; i < listView.Columns.Count; i++)
                totalColumnWidth += Convert.ToInt32(listView.Columns[i].Tag);

            // Calculate the percentage of space each column should 
            // occupy in reference to the other columns and then set the 
            // width of the column to that percentage of the visible space.
            for (int i = 0; i < listView.Columns.Count; i++)
            {
                float colPercentage = (Convert.ToInt32(listView.Columns[i].Tag) / totalColumnWidth);
                listView.Columns[i].Width = (int)(colPercentage * listView.ClientRectangle.Width);             
            }
        }
    }

    // Clear the resizing flag
    Resizing = false;
}

In the example below, there are three columns with FillWeights of 1, 2, and 1 respectively. Thus, the first and third column should occupy 25% of the ListView’s visible space and the second should occupy 50%. The results of the automatic sizing are shown for various form widths below.

Note that if you have multiple ListView controls on a form for which you want to use this logic, you can just hook up each SizeChanged event with the same code as shown below. For this reason, I casted the sender object to a ListView instead of just referencing it directly.

public Form1()
{
    InitializeComponent();
    this.listView1.SizeChanged += new EventHandler(ListView_SizeChanged);
    this.listView2.SizeChanged += new EventHandler(ListView_SizeChanged);
    this.listView3.SizeChanged += new EventHandler(ListView_SizeChanged);    
}     

C#: Programmatically Centering a Control (Extension Method)


I have recently been working on ensuring that one of our Windows Forms applications renders correctly under all DPI settings. One of the things I needed to do was center a control in its parent container at runtime. I came up with the following three extension methods that are available to anything that extends the System.Windows.Forms.Control class. The following code will center the control based upon its parent control. Thus if the control is placed directly on the form, it will be centered in the form. On the other hand if the control is inside a GroupBox or similar container, the control will be centered relative to the bounds of the container.

public static class Positioning
{
    /// <summary>
    /// Centers the control both horizontially and vertically 
    /// according to the parent control that contains it.
    /// </summary>
    /// <param name="control"></param>
    public static void Center(this Control control)
    {
        control.CenterHorizontally();
        control.CenterVertically();
    }

    /// <summary>
    /// Centers the control horizontially according 
    /// to the parent control that contains it.
    /// </summary>
    public static void CenterHorizontally(this Control control)
    {
        Rectangle parentRect = control.Parent.ClientRectangle;
        control.Left = (parentRect.Width - control.Width) / 2;
    }

    /// <summary>
    /// Centers the control vertically according 
    /// to the parent control that contains it.
    /// </summary>
    public static void CenterVertically(this Control control)
    {
        Rectangle parentRect = control.Parent.ClientRectangle;
        control.Top = (parentRect.Height - control.Height) / 2;
    }
}

// Usage
// -----
// private void Form1_Load(object sender, EventArgs e)
// {
//     this.button1.CenterVertically();
//     this.button1.CenterHorizontally();
//     this.button1.Center();
// }
Follow

Get every new post delivered to your Inbox.

Join 68 other followers