Extending .Net Compact Framework Controls

Hello, and welcome to blue collar.

My name is Dan Elliott and I'm a software development engineer in the test organization for the .Net Compact Framework. In my nearly 14 years at Microsoft I've worked in a variety of roles in user education, testing, and development. For the past six years I've tested the execution engine for the Compact Framework (CF). I'm currently starting a new challenge: testing the GUI components of the CF base class libraries.

So why blue collar? I want this blog to address solutions for developers who are in the trenches, attempting to deliver software to end-users on time and under budget. I've worked on end-user applications both inside and outside of Microsoft. In my experience, the single most time consuming task has been determining why the system and framework software that I was relying on didn't work the way I expected. The .NET Framework has provided a great foundation on which developers can build their applications. The .NET Compact Framework has done a good job of providing a useful subset of that functionality for mobile developers. However, to be perfectly honest, no software platform is perfectly designed or engineered, particularly those as ambitious as .Net and .Net CF. I hope to use my experience with software in general and the Compact Framework in particular to provide solutions for those of you doing the real work.

So I'll jump right in. One of the comments I've heard frequently since I began working on the CF GUI base class libraries (BCLs) is "The .Net Framework has an X property (or method or event) on control Y. I really need it, but the CF version doesn't have it. Why?"

When working on devices, memory is limited. The CF provides roughly 28% of the functionality of the .NET Framework in 8% of the space. The only way to achieve that was to leave out everything that wasn't absolutely essential. That's all well and good, but you still need the functionality. Do you have to write your own control from scratch? Thankfully, the answer is usually no.

To take a specific instance, the Compact Framework version of the ListView control (System.Windows.Forms.ListView) doesn't fire the Resize event when the control's size changes. If you want to adjust the width of columns in the control when the control is resized, it would be nice to be notified. It only takes a few lines of code to remedy the problem.

Here's what we need to do:

  1. Add New PocketPC 2003 Control Library project called ListViewThatFiresResizeEvent.

  2. Rename UserControl1.cs to ListViewThatFiresResizeEvent.cs. When prompted, choose to rename all references to the code element UserControl1 .

  3. Change base class of ListViewThatFiresResizeEvent from Control to ListView :

    
      public partial class ListViewThatFiresResizeEvent : ListView
    
  4. In ListViewThatFiresResizeEvent.InitializeComponent method remove the following line because System.Windows.Forms.ListView doesn't contain an AutoScaleMode property:

    
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
    
  5. Remove the OnResize event handler in UserControl1.Designer.cs if one was generated.

  6. In the the ListViewThatFiresResizeEvent namespace, declare an event handler delegate:

    
      public delegate void ResizeEventHandler(object sender, EventArgs e);
    
  7. In the ListViewThatFiresResizeEvent class, declare the Resize event:

    
      public new event ResizeEventHandler Resize;
    

    The new keyword is required because System.Control.Resize is not virtual.

  8. Override the ListView.OnResize event handler in the ListViewThatFiresResizeEvent class:

    
      protected override void OnResize(EventArgs e) 
      { 
        if (null != this.Resize) 
        { 
          this.Resize(this, new EventArgs()); 
        }
      }
    
  9. Implement new handlers for the properties that change the size of the ListView control ( Size , Width , Height ). In each of the property setters, fire the Resize event. (Again the new keyword is required because the properties are not declared virtual in the base class.)

    
      public new Size Size 
      {
        get { return base.Size; }
        set 
        {
          base.Size = value; 
          this.OnResize(new EventArgs()); 
        }
      }
    
      public new int Width 
      {
        get { return base.Width; }
        set 
        {
          base.Width = value; 
          this.OnResize(new EventArgs()); 
        }
      }
    
      public new int Height 
      {
        get { return base.Height; }
        set 
        {
          base.Height = value; 
          this.OnResize(new EventArgs()); 
        }
      }
    
    
  10. Finally, drag a ListViewThatFiresResizeEvent object from the toolbox to your form and add an event handler function in your application.

That's it. A similar process can be used to extend any CF control. Let me know you find this useful.

~Dan

[edited to fix formatting]