Silverlight 3 Launches and Blend 3 RC is Released

Today is the launch of Silverlight 3! Also being released is a release candidate of Expression Blend 3!

Here is the official launch site and here is a new Microsoft site on Silverlight. The silverlight.net site has been updated as well.

One of my favorite new features of Silverlight 3 is, of course, Pixel Shader Effects. The Microsoft Silverlight site has a great overview of the main features and one of those sections is on these GPU rendered effects. Here is a link to a Silverlight 3 application that lets you play with them.

In honor of the Silverlight 3 launch, I have updated my test harness for my blend mode effects library. These effects, of course, are implemented with the new Pixel Shader Effects.

And, let’s not forget Blend! Here is Christian Schormann’s blog post announcing the Expression Blend 3 RC. In this version of Expression Blend, Sketch Flow is finally being released to the general public. This is an awesome tool that is geared toward the early, conceptual design phase and enables one to quickly mock up concepts allowing you to explore ideas at a much lower cost. SketchFlow is just the tip of the iceberg of what’s new in Blend 3. I personally just love the usability improvements (for example, the direct selection improvements) … but what about behaviors (1, 2, 3)? Whoa! Can we say powerful?!

Here is the link to download the Silverlight 3 Tools for Visual Studio 2008 SP1.

Here is the link to download the Expression Blend 3 + SketchFlow RC.

Here is the link to latest version of the Silverlight Toolkit (July 2009) which also released in conjunction with the Silverlight 3 release.

A bunch of blog posts are hitting the internet about these releases and I see that Scott Guthrie’s highly anticipated post has finally been published.

Woot! Woot! Go Silverlight 3 and Blend 3!

Blend Modes, Part III

After I gave you the blend mode library for both WPF and Silverlight, you thought, “Finally! I can do some really cool stuff … and what’s even better … it will run on the GPU!” Then, you started playing with it a little and you ran into some limitations.

In this third blog post in the series (Part 1 and Part 2), I will explore these limitations and show you how you can use Jeremiah Morrill’s GlassBehavior (which with his permission I have renamed to BackgroundEffectBehavior) to get around some of them.

Let’s jump in.

Sometimes you’ll have two images of the exact same size that you want to blend together using one of the blend modes in my library. That is:

<!-- Blending Two Images Together -->
<Image
    Grid.Column="2"
    Width="325"
    Height="244"
    Source="Resources/summer_325x244.jpg"
>
    <Image.Effect>
        <bme:PhoenixEffect>
            <bme:PhoenixEffect.BInput>
                <ImageBrush ImageSource="Resources/fall_325x244.jpg"/>
            </bme:PhoenixEffect.BInput>
        </bme:PhoenixEffect>
    </Image.Effect>
</Image>

The above is easy. As you can see, you just choose one of the images and set the blend mode effect on it. This actually causes that image to become the ‘A’ input (remember: A + B = R). Then, you simply set the ‘B’ input of the blend mode effect to the second image.

But it isn’t always that easy, is it?!

Many times when a designer is thinking of blend modes they aren’t thinking “Ok, I have two images and I want to blend those together.” They often are thinking, “I have this shape and I want to blend it into its background using a cool blend mode.”

Take a look at the following. Here I have a shape, a gray (#FF808080) ‘H’, on top of an image:

HOnImage600

And, here I have the gray ‘H’, blended into its background image using the Color Burn blend mode:

HOnImageColorBurn600

Now, anywhere I move that ‘H’ … it is going to look different because it is being blended into its background, similar, of course, to making a shape transparent (although with different math).

So, how would I do this with the blend mode library that I’ve provided? Well, it would seem easy … and here is a valiant try:

<Grid Width="240" Height="150">
    <Grid.Resources>
        <SolidColorBrush x:Key="solidColorBrush" Color="#FF808080"/>
        <Path
            x:Key="path"
            Width="168.367"
            Height="152.44"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Stretch="Uniform"
            Data="(removed for clarity)"
            Fill="{DynamicResource solidColorBrush}"
        />
    </Grid.Resources>

    <Image
        Source="Resources/MSwanson - Wide - Water 06.jpg"
        Stretch="Uniform"
    >
        <Image.Effect>
            <bme:ColorBurnEffect>
                <bme:ColorBurnEffect.BInput>
                    <VisualBrush Visual="{StaticResource path}"/>
                </bme:ColorBurnEffect.BInput>
            </bme:ColorBurnEffect>
        </Image.Effect>
    </Image>
</Grid>

In the above, I am using the Image as the ‘A’ input and then passing the shape (Path) in as a VisualBrush for the ‘B’ input on the color burn blend mode effect. Here is what happens, though:

HOnImageColorBurn600NoCigar

What is going on? Well, if you recall from Greg Schlecter’s series (1 and 2) on multi-input pixel shader effects (which is how the blend modes are implemented), the inputs have to be either a VisualBrush or an ImageBrush and the inputs have to be the same size. If they are not, the second input is resized to match the first input.

So, our ‘H’ path is getting sized bigger to match the image’s size and the parts outside of the path are taking part in the blending that is occurring (i.e. the dark areas outside the ‘H’) as well.

Greg Schlecter suggests (in the aforementioned articles) how you can solve the ‘resizing’ issue … by using the Viewbox property on the brush.

But, let’s take a step back here. Do we really want to apply the blend mode effect to the background? No, we don’t, as that would limit us to having only one effect per background. For that matter, it is also not very intuitive as you typically think of blending the shape into the background which suggests that it makes more sense to apply effect to the shape.

While thinking about how to solve this problem, I ran into this WPF forum post. I first thought, “Oh, no! I’m up a creek without a paddle.” But, then I dove in on Jeremiah Morrill’s GlassBehavior … and got it too work (at least for certain situations)!

(I’m not going to cover behaviors in this blog post, but they are basically something new with Expression Blend 3.x. They are an implementation of the attached property behavior pattern and allow the designer inside of Blend to drag and drop behaviors onto elements in the element tree. See here and here for more info.)

Jeremiah’s GlassBehavior is a behavior that let’s you apply an effect to the background underneath the element that you are attaching the behavior to. He uses it to apply a SmoothMagnifyEffect (to get a glass like appearance) … but you can really use it to apply any effect. And that is just what I did.

Take a look at this xaml:

<Grid>
    <Grid x:Name="grid">
        <Image
            x:Name="image"
            Source="Resources/MSwanson - Wide - Water 06.jpg"
            Stretch="Uniform"
        />
    </Grid>
    <Canvas Width="168.367" Height="152.44">
        <Path
            Width="168.367"
            Height="152.44"
            Stretch="Uniform"
            Data="(removed for clarity)"
            Fill="{StaticResource solidColorBrush}"
        >
            <i:Interaction.Behaviors>
                <local:BackgroundEffectBehavior
                    Visual="{Binding ElementName=grid, Mode=OneWay}"
                >
                    <local:BackgroundEffectBehavior.Effect>
                        <bme:ColorBurnEffect>
                            <bme:ColorBurnEffect.BInput>
                                <ImageBrush>
                                <ImageBrush.ImageSource>
                                <DrawingImage>
                                <DrawingImage.Drawing>

                                <GeometryDrawing
                                    Brush="{StaticResource solidColorBrush}"
                                >
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>

                                </DrawingImage.Drawing>
                                </DrawingImage>
                                </ImageBrush.ImageSource>
                                </ImageBrush>
                            </bme:ColorBurnEffect.BInput>
                        </bme:ColorBurnEffect>
                    </local:BackgroundEffectBehavior.Effect>
                </local:BackgroundEffectBehavior>
            </i:Interaction.Behaviors>
        </Path>
    </Canvas>
</Grid>

First of all, notice how the BackgroundEffectBehavior attaches to the Path through the attached property collection i:Interaction.Behaviors. This is how the behavior hooks its functionality into Path.

The BackgroundEffectBehavior’s Visual is set to the background (the grid which is holding the image) … and the BackgroundEffectBehavior’s Effect is set to the ColorBurnEffect which has a SolidColorBrush as its ‘B’ input. I also have the same SolidColorBrush set as the Fill of the Path … but this is just so that I can see it in the designer … as at runtime … this behavior kicks in and that Fill is not used.

This is what we get from the xaml above … but basically … success! 🙂

HOnImageColorBurn600Success

Now, a few caveats. 🙁 This whole thing seems to be very fragile.

For example, in order to get this to work, I had to put the image inside the grid … as a sibling to the Canvas that contains the ‘H’ path. Certain other ways of doing it didn’t work. For example, if I set the BackgroundEffectBehavior’s Visual to the grid which contains both the grid/image and the ‘H’ path … it doesn’t work.

Also, if you change the StaticResource(s) to DynamicResource(s) … it doesn’t work.

Another issue is that using this behavior inside of Blend … does not result in what-you-see-is-what-you-get (WYSIWYG) blending. That is why I also set the Fill of the Path above to the same SolidColorBrush that I used as my ‘B’ input to the color burn blend mode effect. In that way, at least, I can see the ‘H’ inside of Blend.

Finally, I have not done any performance analysis (yet) of this, but the BackgroundEffectBehavior uses two VisualBrush(es) to get its job done. So, if you use a lot of these, I wouldn’t be surprised if it starts slowing stuff down.

The best solution here, is really for Microsoft to bake blend modes into the platform. Unfortunately, blend modes will not be in next release of WPF (.NET 4.x) … but the good news is that Brendan Clark from Microsoft says he’s pushing for it.

Here is the code. Unfortunately, the BackgroundEffectBehavior is WPF-only right now (I hope to fix this), but I have updated the Silverlight test harness to have the gradient and image test harnesses. Enjoy!

Here is a live Silverlight 3 test harness (you will need the Silverlight 3.0 runtime, 3.0.40624).

HelloWorldColorBurn600

p.s. I just want to give a shout-out to Mike Swanson and his wallpaper images. They rock. Period. The water droplet background I am using above is one of his.

Blend Modes for Silverlight

Given the great response to my series on Blend Modes … I decided to quickly convert the library so that it could be compiled for the Silverlight platform. I pretty much copied how the WPF Pixel Shader Effect Library did it. Oh, and I renamed a bunch of things too.

So, here it is … the new and improved blend mode effects library … now with a little Silverlight love!

p.s. And here are the WPF binaries and here are the Silverlight binaries.

p.s.s. I now have a live Silverlight test harness (you will need the Silverlight 3.0 runtime, 3.0.40624).

Blend Modes, Part II

In Part I of this series, I showed how I was able to eventually figure out how to create the Linear Burn blend mode effect and how to apply this effect to a Border element.

In Part II of this series, I am going to start off by showing how I was able to truly verify that I had written the Linear Burn blend mode effect correctly. And, then, I will share a few of the A + B = R gradient squares for a few of the blend modes that Paul Dunn’s post didn’t have. Finally, I will share the full blend mode effect library and the test harnesses that go with it.

So … here we go …

With the Linear Burn blend mode effect that I had created, it bothered me that the gradient that I had blended with the green … was white to gray … and not white to black as Robby’s post had shown. Was I doing things correctly? Was the HLSL that I written, right?

A little more searching and I ran into Paul Dunn’s post on Photoshop’s blend modes. Ah! Perfect! Exactly what I wanted, and sure enough, I had written Linear Burn correctly. Check out the screen shot below (from my test harness) and compare it to what you see on Paul Dunn’s post. A match. Whew!

linearburnverified.png

 

At that point, I started creating and going through every blend mode in his blog post, verifying each along the way. This went along fine until I hit the Vivid Light blend mode. The math that he had just wasn’t working. I tried to figure out what was wrong with it, but eventually I ran into another post that had a different way of expressing the math … it was in HLSL! Plugging in this HLSL worked! And what’s better, he had some additional effects that could be added to the library I was creating. And, so, I finished it off.

Now, as mentioned above, mouaif’s post had some blend mode effects that Paul Dunn’s post didn’t show visually. And, so, I will share those here:

Glow Effect

gloweffect.png

 

 

Reflect Effect

  reflecteffect.png

 

Hard Mix Effect

 hardmixeffect.png

 

Negation Effect

 negationeffect.png

 

Phoenix Effect

 phoenixeffect.png

 

Finally, Nathan’s post had a visual way of verifying things as well (near the bottom) and so I included in my test harness a window that let’s you apply the various blend mode effects to images from Nathan’s page. Here’s a screen shot of that window (with the Phoenix blend mode effect applied … which I think looks cool):

Test Harness Window (Images)

 

Without any further adieu, here’s the blend mode effects library and the test harness. All the same caveats apply to what you need on your machine to build the sample code (.NET 3.5 SP1, DirectX SDK, and the Shader Effects BuildTask and Templates from the WPF Futures stuff on CodePlex).

If you don’t want to build the library and test harness yourself … here are the binaries.

Also, I now have a live Silverlight test harness (you will need the Silverlight 3.0 runtime, 3.0.40624). 

Enjoy!

p.s. Thanks to Kevin Moore for the Color Picker that I used in this sample code. I believe I created that Color Picker from an article he did at one point. In fact, I think that some variant of this Color Picker ended up in his Bag-o-Tricks.

Blend Modes, Part I

A while back (now some time ago), I was inspired by Robby Ingebretsen’s post on blend modes that were made possible with pixel shader effects, a new feature of .NET 3.5 SP1. In his post, he suggested that someone take a weekend and create a library of these effects for the community to use. Well, a little late, but I have eventually gotten around to this and done so … because I wanted to give a designer I work with some power tools that he is familiar with in applications like Photoshop.

In this trio (1, 2, 3) of blog posts, I will not be covering how to create a shader effect in WPF, Greg Schlecter has a great introductory series on that already. In particular, it is the multi-input shader effects that make blend modes possible, so be sure to read all the way through his series.

In order to write this library of blend mode effects, I first needed to find the math behind them. Then, I needed to convert this math into the proper HLSL. And finally, I needed some way to verify that the HLSL that I had written … was actually correct. I will cover these topics in the first two blog (first, second) posts.

In the third blog post, I will show how you can use Jeremiah Morrill’s GlassBehavior to blend two shapes with differing geometries.

So … let’s jump in.

I quickly started off with a simple Google search and it led me to Nathan Moinvaziri’s post which is all the blend mode math in C. So, I decided to buckle down and see if I could do Linear Burn … which is the subject of Robby’s post. Nathan had the math (for each channel) for Linear Burn as:

#define ChannelBlend_Subtract(B, L)
     ((uint8)((B + L < 255) ? 0 : (B + L – 255)))
#define ChannelBlend_LinearBurn(B, L)
     (ChannelBlend_Subtract(B, L))

 

Just plugging in the macro definitions into the .fx file didn’t work and through some trial and error, I discovered that the correct HLSL was:

inputColor.r = inputColor.r + blendColor.r - 1;
inputColor.g = inputColor.g + blendColor.g - 1;
inputColor.b = inputColor.b + blendColor.b - 1;

 

This finally gave me the blending Robby had talked about in his post:

Linear Burn

Following is the xaml for the above rectangle which is using the Linear Burn blend mode effect:

<Border
    Width="300"
    Height="100"
    Margin="0,10"
    Background="#FF6AB400"
>
    <Border.Effect>
        <bme:LinearBurnEffect>
            <bme:LinearBurnEffect.Texture>
                <ImageBrush>
                    <ImageBrush.ImageSource>
                        <DrawingImage>
                            <DrawingImage.Drawing>
                                <GeometryDrawing>
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                    <GeometryDrawing.Brush>
                                        <LinearGradientBrush
                                            StartPoint="0,0"
                                            EndPoint="0,1"
                                        >
                                            <GradientStop
                                                Color="#FFFFFFFF"
                                                Offset="0"
                                            />
                                            <GradientStop
                                                Color="#FF808080"
                                                Offset="1"
                                            />
                                        </LinearGradientBrush>
                                    </GeometryDrawing.Brush>
                                </GeometryDrawing>
                            </DrawingImage.Drawing>
                        </DrawingImage>
                    </ImageBrush.ImageSource>
                </ImageBrush>
            </bme:LinearBurnEffect.Texture>
        </bme:LinearBurnEffect>
    </Border.Effect>
</Border>

As you can see above, it is rather easy to apply the blend mode effect. Each blend mode effect takes two shader effect inputs (where input is a shader effect sampler input).

The first input is the element it is set on which is in this case the Border element with the #FF6AB400 background.

The second input is the ImageBrush (it can also be a VisualBrush) that is set on the Texture property. Notice that the alpha channels for the GradientStop(s) are set 100% and not 50% like the Border with opacity overlay (see the attached code, .zip file below). That is, the two layers are being blended by the blend mode effect and not with opacity.

Another thing to mention is that the first input maps to A in the picture above and the second input maps to B in the picture above. R maps to the blend result which is what the user sees. In the next post, I will use this mapping (A + B = R) to illustrate what each blend mode effect does.

Here is the code for this post and here are the binaries. Also, I now have a live Silverlight test harness (you will need the Silverlight 3.0 runtime, 3.0.40624).

Enjoy!

(To build the above sample code, you need .NET 3.5 SP1 and you need a version of the DirectX SDK installed on your machine. Besides all that, you must also install the Shader Effects BuildTask and Templates from the WPF Futures CodePlex site.)

Code to Work Along With While Watching Jason Dolinger’s M-V-VM Video

I meant to post this to my blog sometime ago … but I forgot. I was recently reminded about it when a fellow software engineer I work with was looking for good information on M-V-VM.

I pointed him to my answer to a StackOverflow question on the matter and then pointed him to Jason’s video … sending him at the same time the code that I captured while working through this great video/screen cast. But, hey, why not share this with the wider community?!

What’s great about this sample code is that I’ve captured ‘snapshots’ along every step of the way.

Enjoy, and I would appreciate you leaving a comment if you find it useful. It’s always fun to know that you’ve helped someone.

p.s. I didn’t start out at ground zero for this code, Robert’s code helped me get started. So, thanks Robert!

UI Design for Developers

In light of my previous post on design for developers, I thought I would also go ahead and also quickly point to Arturo Toledo’s blog and his UI Design for Developer Series. Arturo is designer who is a product manager at Microsoft and his blog has loads of designer goodies and links.

In this particular goodie, Microsoft has produced (with Total Training) 13 videos and has even provided the assets so you can work along while you watch. In his blog post, Arturo provides links to both the videos and assets, and I provided them here, as well, for convenience.

uidesignfordevelopers

1. Principles of Design: Learning about Balance

Video

Assets

2. Principles of Design: Learning about Rhythm

Video

Assets

3. Principles of Design: Learning about Emphasis

Video

Assets

4. Principles of Design: Learning about Symmetry & Asymmetry

Video

Assets

5. Principles of Design: Learning about Unity

Video

Assets

6. Principles of Design: Learning about Points, Lines, & Form

Video

Assets

7. Choosing Colors to Complement Your User Interface

Video

Assets

8. Experimenting with User Interface Colors

Video

Assets

9. Creating Mosaic & Tiled Patterns

Video

Assets

10. Learning to Create Icons

Video

Assets

11. Creating a Sample Icon

Video

Assets

12. Designing a Glassy Button

Video

Assets

13. Applying Effects to Bitmap Images

Video

Assets

He promises that he is already working on Part II of this series!

By the way, I love this trend to teach design basics to developers, because I think it is only through a mutual sharing of knowledge, from designer to developer and vice-versa, that we are truly going to capitalize on these awesome UX technologies like WPF and Silverlight.

Design Fundamentals for Developers

Robby Ingebretsen’s MIX09 workshop, Design Fundamentals for Developers, is now online! If you can’t tell from my earlier post about Kaxaml, I’m a big fan of Robby’s, and this session is 3 hours of pure goodness.

Design Fundamentals for Developers
Click on the image to watch the session streamed at the MIX09 site.

From the MIX09 summary:

From colors to wireframes, this workshop introduces you to the fundamental principles and techniques of application design. The workshop is tuned especially for people who have some background in coding. If you are a developer who is working more frequently with designers, evolving to become a designer yourself, or simply a manager who needs to make sure that both roles work smoothly together, this session is an invaluable opportunity to jump-start the process.

In a world where development and design are converging in UX technologies like WPF and Silverlight, this is a free workshop that you will want to watch! Especially if you are developer with designer tendencies … like me.

Jamie Rodriguez from Microsoft has kindly provided three download links to each of the three parts:

  1. Part I: Process
  2. Part II: Composition
  3. Part III: Visuals

A big thanks to Robby for putting such a high quality workshop together … and thanks to the Microsoft guys like Jamie who posted it online. Woot!

WPF & Memory Leaks

The Red Herring:

Recently, I had to track down why all of our new WPF screens were leaking memory like a sieve. A coworker of mine ran into a discussion on the WPF forum and my jaw dropped. I rapidly dove into this issue and soon discovered that this issue was not really the one causing us problems (that I could tell). It seems as if this issue only raises its ugly head in certain situations (see the post for more detail).

The Awesome Tool:

memprofiler.png

At this point, we ran into a tool that, in my opinion, is a must have if you are trying to find memory leaks in a .NET application. It is called (aptly enough), .NET Memory Profiler and it is made by a company called SciTech software. Previously, we had been using AQtime and I still would recommend that tool for performance profiling but when it comes to memory allocation profiling (i.e. memory leaks), it is quite slow. The .NET Memory Profiler doesn’t do performance profiling and focuses exclusively on memory allocation profiling. I think this has made it the best tool out there. I have tried Jet Brains dotTRACE as well, which is also very fast, but the .NET Memory Profiler beats that one hands down in how it presents the information to the user and how it allows you to navigate through all the objects that have been created or are still living on the heap. They do offer a free 14-day trial and I would recommend that you try their 3.5 version which you can preview now. This version has a very nice feature that they call Automatic Memory Analysis, which is basically tips and warnings regarding common memory usage issues.

The Real Issue:

Using this tool and some grit, the previously mentioned coworker and I finally ran into the issue that was causing us problems. It is a known issue. Personally, I love what it says at the knowledge base article just referenced:

When you use data binding in Microsoft Windows Presentation Foundation (WPF), a memory leak may occur.

Ha! Are you kidding me?!

You can check out the knowledge base article for more info, but basically, if you are binding to something that isn’t a DependencyProperty or doesn’t implement INotifyPropertyChanged, WPF tries to use the ValueChanged event. In doing so, it calls PropertyDescriptor.AddValueChanged which creates a strong reference from the property descriptor to the object being bound to.

Something as simple as the following xaml causes a leak:

<Label Name="MyLabel">
    <Stack Panel Name="MyStackPanel">
        <TextBlock Text="{Binding ElementName=MyStackPanel, Path=Children.Count}" />
    </StackPanel>
</Label>

One way that you can verify that this issue is causing you problems is to see PropertyDescriptor in the root path. Check out this screen capture:

rootpath.png

The Solution:

So, how did we rid ourselves of this problem? Well, we basically went in and modified the objects that were causing us leaks to inherit from INotifyPropertyChangedeven if we didn’t really want to notify anyone of changes. In the those cases, we would #pragma the CS00067 warning away that came from not using the PropertyChanged event:

public class SomeClassBeingDataBoundTo : INotifyPropertyChanged
{
    // class implementation

#pragma warning disable 0067
    // If you data-bind to a regular .NET property on a regular .NET object, that object will never get garbage-collected.
    //    •    Dependency properties are not affected.
    //    •    Objects implementing the INotifyPropertyChanged interface are not affected.
    public event PropertyChangedEventHandler PropertyChanged;
#pragma warning restore 0067
}

How the heck did I miss this?

So, after all the excitement subsided, I did a Google search to see if I could find any other blogs that talks about this problem.  Heh heh. The link at the top of search results … was about our issue. Argh! I don’t know how I missed it before when I was doing my original research.

Even better, the search results brought up Jossef Goldberg’s priceless post on finding memory leaks in WPF applications (that I’ve run into before). That post is a must read if you are trying to find leaks in your WPF applications. And, yes, it too, talks about our issue.

Someone, please take my software engineering card away.

I hope my pain is someone else’s gain.

Snoop Now Works in WPF Interop Scenarios, Part II

First off, in my previous post, I made the mistake of assuming (given the new look and new functionality) that Pete Blois had bumped the version of Snoop up to 2.0. This does not seem to be the case. So, oops! My apologies!

Now, onto the meat of post: I have found a couple more places where you need to insulate yourself from not having a current Application … and I was able to fix the keyboard issue!

Let’s tackle the keyboard issue first as that is the big one. In the Inspect method of the SnoopUI class, you need to call the static method ElementHost.EnableModelessKeyboardInterop and you need to do that when in an interop scenario, that is, when the current Application is null.

The MSDN documentation for this method states that this method allows a System.Windows.Window to receive keyboard messages correctly when opened modelessly from Windows Forms (our interop scenario). Hmm. Sounds exactly like what I was looking for!

public void Inspect(object target)
{
    this.rootObject = target;
    this.Load(target);
    this.CurrentSelection = this.root;

    this.OnPropertyChanged("Root");

    if (Application.Current != null)
    {
        this.Owner = Application.Current.MainWindow;
    }
    else
    {
        ElementHost.EnableModelessKeyboardInterop(this);
    }
    this.Show();
}


This also requires you to add a reference to WindowsFormsIntegration.dll and to add a using statement:

using System.Windows.Forms.Integration;

With the above changes, you should be able to use the keyboard once again to change property values in the property grid that comes up when you Snoop something. Whew! That copy/paste trick was getting old, really fast.

Now, onto the additional places where you need to protect yourself from not having an Application instance. First, the Previewer was broken … and you need to modify the HandleMagnify method of the Previewer class:

private void HandleMagnify(object sender, ExecutedRoutedEventArgs e)
{
    Zoomer zoomer = new Zoomer();
    zoomer.Target = this.Target;
    if (Application.Current != null)
        zoomer.Owner = Application.Current.MainWindow;
    zoomer.Show();
    e.Handled = true;
}


Second, you need to modify the ProcessFilter method of the SnoopUI class so that it uses the Dispatcher for the current thread versus grabbing it off the non-existent Application instance:

private void ProcessFilter()
{
    this.filtered.Clear();

    // Blech.
    if (this.filter == "Clear Filter")
    {
        Dispatcher dispatcher = null;
        if (Application.Current == null)
            dispatcher = Dispatcher.CurrentDispatcher;
        else
            dispatcher = Application.Current.Dispatcher;

        dispatcher.BeginInvoke
        (
            DispatcherPriority.Loaded,
            new DispatcherOperationCallback
            (
                delegate(object arg)
                {
                    this.Filter = string.Empty;
                    return null;
                }
            ),
            null
        );
        return;
    }
    if (this.filter == "Visuals with binding errors")
        this.FilterBindings(this.root);
    else if (this.filter.Length == 0)
        this.filtered.Add(this.root);
    else
        this.FilterTree(this.root, this.filter.ToLower());
}

By the way, I would love to hear (by leaving a comment on the blog here), if this helps you at all. I was truly missing the ability to Snoop our WPF interop application myself.

Enjoy!

p.s.

I would love to make my source code modifications to Snoop readily available to the general public, but I have been unable to contact Pete Blois and obtain his permission to do so. Sorry!

(The source code and binaries for Snoop are now (see posts: 1, 2) up on CodePlex. Please go download it from there as that code will contain the latest and greatest bits.)