Technical Blog Posts

.NET Extension methods and ListView control 

Friday, October 16, 2009 3:15:57 PM
Rate this Content 0 Votes

As it goes every Microsoft .NET framework release brings new stuff with it and it is usually exciting.

On many ocassions while programming Windows Forms applications in .NET I find myself virtually with a "chopped hand" because some useful functionality has been left out of the class implementation in the .NET framework.

One of the new additions in .NET 3.5 was Extension Methods. It can be used for a lot of things such as extending frameworks when functionality is missing. At the same time it offers certain protection mechanisms so that you don't destroy the framework you are extending by going wild on extension methods.

Sure, the problem is many programmers out there (typically undisciplined or inexperienced) will just jump at using extension methods for everyting. I can imagine people doing extensions rather than creating their own object oriented frameworks. So, yes, there is the possibility for abuse that have very undesirable consequences.

This time however, I was working with a ListView control in a Windows form application and needed to do a few things that were not possible with the default ListView control from the framework. I thought it would make a good example for using extension methods.

The problems I had at hand with the list view were:

  • I needed to be able to clear all the items selected in the ListView. In other words unselect them while keeping them in the List View
  • I needed to be able to delete the selected items from the List View
  • I needed to implement a hover effect so that the background color of the row would change when you hovered the mouse over it without actually selecting it. The list view offers a hover feature but only for selecting them when you hover, that is not what I wanted or needed.

I created the ListViewExtensions static class in the System.Windows.Forms.Extensions namespace (see code below). In my application (the windows form) I need to add a "using System.Windows.Forms.Extensions;" statement and I will be able to access them and have Intellisense too.

For the first bullet item above I created the ClearSelectedItems() extension method. It goes through the list of selected items (whether it is single or multiple) and deselects them.

For the second bullet item I created the RemoveSelectedItems() extension method. It does the same as the first except it deletes them from the list view rather than deselecting them.

Last but not least, for the third bullet item I wrote the HoveredItemEffect() extension method. I call this method on the list view instance from its ItemMouseHovered event handler as follows:

ListView lv = sender as ListView;
lv.HoveredItemEffect(e.Item, System.Drawing.Color.White, System.Drawing.Color.YellowGreen);

Finally here is the List View extension methods class I talked about.

namespace System.Windows.Forms.Extensions
{
    /// <summary>
    /// Extension methods (.NET 3.5) to extend the ListView control with some
    /// useful methods.
    /// </summary>
    /// <remarks>To use this add a 'using System.Windows.Forms.Extensions;' entry to your code</remarks>
    public static class ListViewExtensions
    {
        /// <summary>
        /// Extension method to clear all the items that have been
        /// selected in the list view
        /// </summary>
        /// <param name="lv">List view control instance</param>
        public static void ClearSelectedItems(this ListView lv)
        {
            for (int x = (lv.SelectedIndices.Count - 1); x >= 0; x--)
            {
                lv.Items[lv.SelectedIndices[x]].Selected = false;
            }
        }

        /// <summary>
        /// Extension method to remove all the items that have been
        /// selected in the list view
        /// </summary>
        /// <param name="lv">List view control instance</param>
        public static void RemoveSelectedItems(this ListView lv)
        {
            for (int x = (lv.SelectedIndices.Count - 1); x >= 0; x--)
            {
                lv.Items.RemoveAt(lv.SelectedIndices[x]);
            }
        }

        /// <summary>
        /// This extension method can be used in a ListView control's ItemHover event to change
        /// the background color of the item being hovered and reverting the previously hovered
        /// item to its regular color. Accomplishes the same effect as enabling HoverSelection
        /// except that we are not forcing an item selection.
        /// </summary>
        /// <param name="lv">List view control instance</param>
        /// <param name="lvi">The list view item <see cref="ListViewItemMouseHoverEventArgs"/> Item property</param>
        /// <param name="normal">The background color for not-hovered items</param>
        /// <param name="hover">The background color for the hovered item</param>
        public static void HoveredItemEffect(this ListView lv, ListViewItem lvi, System.Drawing.Color normal, System.Drawing.Color hover)
        {
            if (lv.Tag != null)
            {   // An item has been previously hovered
                ListViewItem lviOld = (ListViewItem)lv.Tag;
                lviOld.BackColor = normal;   // revert its background color to the standard
            }
            // Now work on the hovered item
            lv.Tag = lvi;    // keep track of it in the list view Tag property
            lvi.BackColor = hover;
        }
    }
}

I hope you find it useful if not at least instructive.

Share This Using Popular Bookmarking Services

Primary Key column metadata in SQL Server 2005 

Wednesday, May 13, 2009 9:46:15 AM
Rate this Content 1 Votes

Recently I found myself writing a database trigger for SQL Server 2005 in which I needed to know the following two things:

  • Find out whether the table in question actually had a primary key column
  • The name of the primary key column of that table

While most solutions out there are based on the simplified case where the table belongs to the default schema (dbo), I normally develop data models modularized in schemas (kind of tablespaces in Oracle). As a result my code snippets take this into account and will get you a long way without having to figure it out yourself.

Finding out if the table has a Primary Key column

This code snippet works in Microsoft SQL Server 2005, I guess it probably works in the 2008 version but I don't have such an instance to test it with. For the sake of an example let us assume we want to check if table 'dyn.LifecycleEvents' has a PK column.

   IF (SELECT [name] FROM sys.tables
        WHERE OBJECTPROPERTY(OBJECT_ID([name]),'TableHasPrimaryKey') = 1
            AND [name] = 'LifecycleEvents'
            AND schema_id('dyn')) IS NOT NULL

  BEGIN
       ..... your code here ....
  END

Obtain the name of the Primary Key column

So, I could find out if the table had a primary key column but if it did (as it should in that case) I also needed to find out the actual name of the primary key column. The following code snippet accomplished that:

    DECLARE @pkName nvarchar(128)
    SET @pkName = (
         SELECT ky.COLUMN_NAME FROM information_schema.table_constraints tbl
                INNER JOIN information_schema.key_column_usage ky
                                  ON tbl.constraint_name = ky.constraint_name
         WHERE tbl.constraint_type = 'PRIMARY KEY'
                    AND tbl.table_name = 'LifecycleEvents'
                    AND tbl.table_schema = 'dyn'
    )

Therefore if table 'dyn.LifecycleEvents' has a primary key column named 'EventName' then that is what it will return.

 

Share This Using Popular Bookmarking Services
Copyright 2009 Blog Author