Welcome to WindowsClient.net | Sign in | Join

March 2008 - Posts

I'm fortunate enough to be attending DevWeek 2008 this week. Today I took in 3 WPF-related sessions by Dave Wheeler (who also presented yesterday's excellent keynote on Silverlight). The talk that was of the most interest to me, and probably to many other people, covered using WPF and Windows Forms together. My current project has got far too much Windows Forms code to consider a re-write at this stage, but there are a couple of interface features I'd like to implement which will be much easier in WPF. It seems this is fairly straightforward (unlike interop between WPF and Win32/MFC, which made me glad I left all that behind).

One of the caveats Dave mentioned was that the ShowDialog method in the Windows Forms Form class requires an IWin32Window type as its argument, and WPF controls don't implement that type or, indeed, have an IntPtr handle. He presented a shim solution which uses the WindowInteropHelper to provide a surrogate handle for WPF Window types:

class Shim : IWin32Window
{
  public Shim(System.Windows.Window owner)
  {
    // Create a WindowInteropHelper for the WPF Window
    interopHelper = new WindowInteropHelper(owner);
  }

  private WindowInteropHelper interopHelper;

  #region IWin32Window Members

  public IntPtr Handle
  {
    get
    {
      // Return the surrogate handle
      return interopHelper.Handle;
    }
  }

  #endregion
}

This set off my current obsession with extension methods, so I scribbled one to wrap this technique, tested it when I got home and it worked fine. Here it is:

namespace System.Windows.Forms
{
  public static class WPFInteropExtensions
  {
    public static DialogResult ShowDialog(
        this System.Windows.Forms.Form form,
        System.Windows.Window owner)
    {
      Shim shim = new Shim(owner);
      return form.ShowDialog(shim);
    }

    class Shim : IWin32Window
    {
      // as above
    }
  }
}

I've lost count of the number of times I've written recursive functions to iterate through all the controls on a form, including those contained in panels or group boxes or group boxes in panels. But hopefully, thanks to C# 3.0 and extension methods, I've just written the last one.

/// <summary>
/// Provides extension methods to the 
///
<see cref="System.Windows.Forms.Control.ControlCollection"/> type. /// </summary> public static class ControlCollectionExtensions { /// <summary> /// Adds a method to recurses through the specified control collection,
/// including the controls within controls etc.
/// </summary> /// <param name="controlCollection">The control collection.</param> /// <returns>An <see cref="IEnumerable&lt;Control&gt;"/>.</returns> public static IEnumerable&lt;Control&gt;
Recurse(this Control.ControlCollection controlCollection) { foreach (Control item in controlCollection) { yield return item; if (item.HasChildren) {
// The recursion point... foreach (var subItem in item.Controls.Recurse()) { yield return subItem; } } } } }

And because this returns an IEnumerable<T>, it's fully Linq-able, which means I can formulate queries such as:

var q = from control in Controls.Recurse()
        where control.DataBindings.Count > 0
        select control;

(which will give me every control with any data-binding happening to it).

I am deeply, deeply happy with C# 3.0.

 
Page view counter