Tuesday, October 28, 2008

ListView Extended Styles in .NETCF

In this article I would like to demonstrate how to extend the ListView control in the .NET Compact Framework. We will focus on enabling some of the ListView Extended Styles. If we take a look at the Windows Mobile 5.0 Pocket PC SDK we will see that there are certain features of ListView that aren't provided by the .NET Compact Framework.

An example of the ListView extended styles is displaying gridlines around items and subitems, double buffering, and drawing a gradient background. These extended styles can be enabled in native code by using the ListView_SetExtendedListViewStyle macro or by sending LVM_SETEXTENDEDLISTVIEWSTYLE messages to the ListView.

Send Message

We will be using a lot of P/Invoking so let's start with creating an internal static class called NativeMethods. We need a P/Invoke declaration for SendMessage(HWND, UINT, UINT, UINT).

internal static class NativeMethods
{
  [DllImport("coredll.dll")]
  public static extern uint SendMessage(IntPtr hwnd, uint msg, uint wparam, uint lparam);
}

Enabling and Disabling Extended Styles

Now that we have our SendMessage P/Invoke declaration in place, we can begin extending the ListView control. Let's start off with creating a class called ListViewEx that inherits from ListView. We need to look into the native header files of the Pocket PC SDK to get the ListView Messages. For now we will only need LVM_[GET/SET]EXTENDEDLISTVIEWSTYLE message which will be the main focus of all the examples. I will declare my class as a partial class and create all the pieces one by one for each example. Let's create a private method called SetStyle(), this method will enable/disable extended styles for the ListView

public partial class ListViewEx : ListView
{
  private const uint LVM_FIRST = 0x1000;
  private const uint LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54;
  private const uint LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55;

  private void SetStyle(uint style, bool enable)
  {
    uint currentStyle = NativeMethods.SendMessage(
      Handle,
      LVM_GETEXTENDEDLISTVIEWSTYLE,
      0,
      0);

    if (enable)
      NativeMethods.SendMessage(
        Handle,
        LVM_SETEXTENDEDLISTVIEWSTYLE,
        0,
        currentStyle | style);
    else
      NativeMethods.SendMessage(
        Handle,
        LVM_SETEXTENDEDLISTVIEWSTYLE,
        0,
        currentStyle & ~style);
  }
}

Grid Lines

For my first example, let's enable GridLines in the ListView control. We can do this by using LVS_EX_GRIDLINES. This displays gridlines around items and sub-items and is available only in conjunction with the Details mode.

public partial class ListViewEx : ListView
{
  private const uint LVS_EX_GRIDLINES = 0x00000001;

  private bool gridLines = false;
  public bool GridLines
  {
    get { return gridLines; }
    set
    {
      gridLines = value;
      SetStyle(LVS_EX_GRIDLINES, gridLines);
    }
  }
}

What the code above did was add the LVS_EX_GRIDLINES style to the existing extended styles by using the SetStyle() helper method we first created.

An interesting discovery to this is that the Design Time attributes of the Compact Framework ListView control includes the GridLines property. Now that we created the property in the code, when we open the Visual Studio Properties Window for our ListViewEx we will notice that GridLines property we created falls immediately under the "Appearance" category and even includes a description :)

Double Buffering

Do you notice that when you populate a ListView control with a lot of items, the drawing flickers a lot when you scroll up and down the list? Although it is not in the Pocket PC documentation for Windows Mobile 5.0, the ListView actually has an extended style called LVS_EX_DOUBLEBUFFER. Enabling the LVS_EX_DOUBLEBUFFER solves the flickering issue and gives the user a more smooth scrolling experience.

public partial class ListViewEx : ListView
{
  private const uint LVS_EX_DOUBLEBUFFER = 0x00010000;

  private bool doubleBuffering = false;
  public bool DoubleBuffering
  {
    get { return doubleBuffering; }
    set
    {
      doubleBuffering = value;
      SetStyle(LVS_EX_DOUBLEBUFFER, doubleBuffering);
    }
  }
}

Gradient Background

Another cool extended style is the LVS_EX_GRADIENT. This extended style draws a gradient background similar to the one found in Pocket Outlook. It uses the system colors and fades from right to left. But what is really cool about this is that this is done by the OS. All we had to do was enable the style.

public partial class ListViewEx : ListView
{
  private const uint LVS_EX_GRADIENT = 0x20000000;

  private bool gradient = false;
  public bool Gradient
  {
    get { return gradient; }
    set
    {
      gradient = value;
      SetStyle(LVS_EX_GRADIENT, gradient);
    }
  }
}

If you want to look more into extended styles then I suggest you check out the Pocket PC Platform SDK documentation. There a few other extended styles that I did not discuss that might be useful for you. You can get the definitions in a file called commctrl.h in your Windows Mobile SDK "INCLUDE" directory.

8 comments:

Yogesh Bhadauriya said...

hi
i m new in CE development.
i m using sqlite in my application
sqlite version 060.
but when i m trying to open database it gives me an error cant find Pinvoke method..
error message is "Can't find PInvoke DLL 'SQLite.Interop.060.DLL'."
i m using system.data.sqlite namespace......
i had also copied the same dll to my windows folder but not succeeded.
Please help me....

Sebastian said...

Hey Christian,

in the Gradient get Field you return "doubleBuffering" where it should be "gradient".

Thanks for the code!!!

Christian Resma Helle said...

Hey Sebastian,

I'll fix that immediately! Thanks for notifying me about it.

Moorthy said...

hi i am new mobile application development , will you give the full source of ListViewEx

Christian Resma Helle said...

Sure, I'll upload it to:
http://cid-ca531e7fb4762c70.skydrive.live.com/browse.aspx/Code%20Samples?wa=wsignin1.0&sa=148255517

Anonymous said...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!

Anonymous said...

i'm trying to override the onpaint for a TextBox inb CF 2.0
Unfortunately i read somewhere i should call SetStyle(ControlStyles.UserPaint) in my constructor in order to see my OnPaint override called.
SetStyle is not there in CF 2.0

Do you know the message to be sent for simulating SetStyle(ControlStyles.UserPaint) via core.dll in CF 2.0 ?

Thanx for the post and for any suggestion

Unknown said...

Hi

Can you do the same but using VB.NET? Im trying to do that but i cant get it

Thanks