WPF Direct3D Interop

May 28, 2008 – 12:49 pm

There are some very interesting posts I missed the last days. Since .NET 3.5 SP1 perfectly integrates WPF with DirectX, a number of cool effects can finally be applied:
http://www.codeproject.com/KB/WPF/WPFPixelShader.aspx

http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx

http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx

Some of those effects were on Dax Pandhi’s wish list for WPF (http://blog.nukeation.com/post/My-wishlist-for-the-next-release-of-WPF.aspx) for quite some time.

More importantly, the integration of WPF and Direct3D might eliminate the need for a custom overlay control for the MenuKiller Control, which is a major performance hog (I currently use an overlay similar to this: http://blogs.msdn.com/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx).

A MenuKiller Control - Draft

May 4, 2008 – 9:52 pm

This is just a draft on my upcoming article. I have asked a number of WPF Gurus to help me out on this…

Introduction

In an effort to take user experience to the next level, designers have come up with ideas on how to solve old problems in a new way. In the last few months, the term “Differentiated User Experience” or simply “Differentiated UX” has come up to describe these efforts.

One of the beforementioned UI designers is Dax Pandhi, who published an article “Rethinking the Button” on his blog which introduced a new control he calls MenuKiller. This control is certainly more than a replacement for the Menu and ContextMenu, as it can be used in ways that are quite different. However, it turns out that changing the way things are typically done is indeed not so easy.

A Screenshot of the MenuKiller

This article gives an overview of my implementation of the MenuKiller and presents a small sample application. It’s written in C# using .NET 3.5 and Visual Studio 2008. What is presented here is not a full-fledged control, since there are quite a number of open todos. Yet, I hope that this motivates the use of different controls and serves as a good starting point for other WPF control development.

Read the rest of this entry »

Prism 10933

April 30, 2008 – 8:35 pm

A new Prism drop has just been released:

http://www.codeplex.com/prism/SourceControl/DownloadSourceCode.aspx?changeSetId=10933

The current prism drop comes with a neat documentation. Unfortunately, I won’t be able to check it out for the next few days…

The StockTraderRI now looks like this: Prism Reference Implementation Screenshot.

Protected: A MenuKiller Sample Application

April 15, 2008 – 2:55 am

This post is password protected. To view it please enter your password below:


ICommand.CanExecute() and NullReferenceException

April 10, 2008 – 6:12 pm

Have you ever tried to call ICommand.CanExecute()? It actually works fine, but only if you are not as naive as I am… Simply calling it without the proper know-how might result in a NullReferenceException, so what you should read is how to implement ICommandSource. See

MSDN: How To: Implement ICommandSource

MSDN: Implement ICommandSource Sample
.

Not a big thing, but since google didn’t show anything for “ICommand.CanExecute NullReferenceException”, it might help somebody I hope…

On UIElement.Opacity and the Removal of Storyboards

April 10, 2008 – 12:50 pm

Today, I encountered two WPF related problems:

1 - UIElement.Opacity and the way it is being ‘inherited’

Every UIElement has an Opacity property, which will we be used when rendering the control. When rendering an object, 0.0 means the object is fully transparent, thereby invisible to the user, while 1.0 means it is fully opaque. Since controls can be composed so simply, it is desireable that child controls will use the opacity of their parents, so you don’t have to set it explicitly for each child.

So there is some kind of opacity stack, which will multiply opacities with each other when traversing down the tree upon rendering. Therefore, a 100% opaque button on a 10% opaque canvas will yield 10% opacity for the button (for an even longer description, see this MSDN entry).

However, it also seemed natural to me that it is well possible to specify an opacity of 2.0, so the child of a half-transparent object is rendered fully opaque (the same math applies). This is, however, not the case. While there are no warnings or exceptions (even the value is preserved), it will be clipped during the rendering process silently, therefore not allowing any UIElement to be more opaque than their parent.

For the MenuKiller Control, that is a catastrophe, since it changes the opacity of children all the time in order to convey the hierarchical concept better.

So, what I came up with is a helper-method that does the whole thing manually… Any thoughts on this one?

I really don’t understand why this is not allowed, since it would make some things a lot easier, at a very low risk of objects that are too opaque.

2 - The need to remove storyboards

When testing the MenuKiller Control, I realized (not for the first time, but the first time it bugged me), that the XAML code I had did not work entirely correct.

The Button has a few triggers, including these:

  1. <!– exact storyboard omitted for clarity –>
  2. <Trigger Property="IsMouseOver" SourceName="contentPresenter" Value="True">
  3.   <Trigger.EnterActions>
  4.     <BeginStoryboard x:Name="MouseOver_BeginStoryboard"
  5.                      Storyboard="{StaticResource MouseOver}"/>
  6.   </Trigger.EnterActions>
  7.   <Trigger.ExitActions>
  8.     <BeginStoryboard x:Name="MouseOut_BeginStoryboard"
  9.                      Storyboard="{StaticResource MouseOut}"/>
  10.   </Trigger.ExitActions>
  11. </Trigger>
  12. <Trigger Property="IsPressed"  Value="True">
  13.   <Trigger.EnterActions>
  14.     <BeginStoryboard x:Name="PressedOn_BeginStoryboard"
  15.                      Storyboard="{StaticResource PressedOn}"/>
  16.   </Trigger.EnterActions>
  17.   <Trigger.ExitActions>
  18.     <BeginStoryboard x:Name="PressedOff_BeginStoryboard"
  19.                      Storyboard="{StaticResource PressedOff}"/>
  20.   </Trigger.ExitActions>
  21. </Trigger>

Expected Behaviour

The button has a trigger for the IsMouseOver property, so this should increase the opacity to 100% if hovering:
Screenshot of the desired hover effect.

Observed Behaviour

This works, but only as long the button is never clicked. If the button is clicked once, it will simply stay at its default 0.7 opacity. The only thing that still works is the animation for IsPressed.

Screenshot of non-hovering Button due to IsPressed Storyboard's ExitAction still pertaining.
(The red dot, by the way, is only a debugging tool, not a mistake)

I wondered how this could happen, trying to figure whether the button might behave like a ToggleButton for some reason. But it didn’t.

Instead, I realized that the trigger system, being based upon EnterActions and ExitActions, would have to preserve the controls’ state somehow. Several storyboards could easily cross each others paths, isn’t it? Interestingly, there is a property called HandoffBehaviour which I did not know until then. Unfortunately, the default value is already SnapshotAndReplace, while the only other option Compose was clearly not what I wanted.

As it turns out, the ExitAction, once applied, will stay on the control as long as the original enter condition is valid. Therefore, one simply has to remove the storyboard explicitly if another animation is supposed to be visible to the user. This yields the following XAML Code:

  1. <Trigger Property="IsMouseOver" SourceName="contentPresenter" Value="True">
  2.   <Trigger.EnterActions>
  3.     <RemoveStoryboard BeginStoryboardName="PressedOff_BeginStoryboard" />
  4.     <BeginStoryboard x:Name="MouseOver_BeginStoryboard"
  5.                      Storyboard="{StaticResource MouseOver}"/>
  6.   </Trigger.EnterActions>
  7.   <Trigger.ExitActions>
  8.     <RemoveStoryboard BeginStoryboardName="PressedOff_BeginStoryboard" />
  9.     <BeginStoryboard x:Name="MouseOut_BeginStoryboard"
  10.                      Storyboard="{StaticResource MouseOut}"/>
  11.   </Trigger.ExitActions>
  12. </Trigger>
  13. <Trigger Property="IsPressed"  Value="True">
  14.   <Trigger.EnterActions>
  15.     <BeginStoryboard x:Name="PressedOn_BeginStoryboard"
  16.                      Storyboard="{StaticResource PressedOn}"/>
  17.   </Trigger.EnterActions>
  18.   <Trigger.ExitActions>
  19.     <BeginStoryboard x:Name="PressedOff_BeginStoryboard"
  20.                      Storyboard="{StaticResource PressedOff}"/>
  21.   </Trigger.ExitActions>
  22. </Trigger>

What it accomplished, in the end, is the newest incarnation of the MenuKiller, here in Debug draw-mode:

Screenshot of the MenuKiller Control in a debug version.

Applying ItemContainerStyle Recursively

April 7, 2008 – 7:23 pm

In the MenuKiller Control, I need to configure a TreeView to quite some extent: I want all nodes to have a certain custom ItemContainerStyle.

First naive approach: The TreeView will apply its ItemContainerStyle to all nodes. Wrong! The TreeViewItems themselves are ItemControls, therefore having their own ItemContainerStyle.

Second approach: Have the ItemContainerStyle refer to itself using a DynamicResource:

  1. <Style x:Key="MKItemStyle" TargetType="{x:Type local:MenuKillerItem}">
  2.     <Setter Property="Template" Value="{StaticResource MenuKillerItemTemplate}"/>
  3.     <Setter Property="ItemContainerStyle" Value="{DynamicResource MKItemStyle}"/>
  4. </Style>

Wrong again! This does not work. Frankly, I don’t know why, but I didn’t bother to debug it.

There are quite some articles on customizing TreeViews the net, for example Josh Smith’s article “Custom TreeView Layout in WPF” at the CodeProject. There didn’t seem to be any such problem… So what’s the catch?

A Simple Solution?

So what is it all about? In the source code accompanying Josh’s article, we find the following declaration:

  1. <!– This Style redefines the ControlTemplate used by TreeViewItems and
  2.        also provides a different itemspanel for their child items. –>
  3. <Style TargetType="TreeViewItem">
  4.   [...]
  5. </Style>

So this will simply apply the defined style to each and every item of the TargetType.
Done!.

There are some drawbacks, though: In a small application, this might be OK, but it may result in problems with larger applications or control libraries. One simple trick, of course, is to create a custom control which derives from the control you want, and apply a default style to this derived type (I currently do this for the MenuKillerItem, which derives from TreeViewItem).

Yet, this solution is not well-templateable either. Users of a control library might want to override the default template only for children of a specific control, which is not possible this way.

Of course, one can write a recursive method to apply the style, but I doubt this is the cleanest solution. Any better ideas?

The MenuKiller Control - Differentiated UX

April 7, 2008 – 6:00 pm

A while ago, I read a very interesting blog post: Rethinking the Button by Dax Pandhi. It really fascianated me, so I started some research on the topic. Apparently, “Differentiated UX” is the new buzzword. As is always the case with buzzwords, different people understand it in different way, but I guess the common denominator is: We haven’t been putting enough effort into User Interfaces, because we simply stuck to what was there (at least, most of us). 

MenuKiller screen shot

With WPF, things have changed quite a bit. What makes a control? In Windows Forms, a control had a certain look and behaviour. Some of it could be modified (e.g. the colors, the way the button behaves on click, etc.), yet a lot of it was fixed. For example, many controls had a Text-Property which accepted a string of course.
WPF Controls, on the other hand, have Content or Items, which can again be controls. So you can finally put an image into a tooltip with a few lines of purely declarative XAML code. Therefore, in WPF, a control is far less specific. Many scenarios that demanded a custom control in Windows Forms are now merely a different content, or a template.

Anyway, I wanted to use Dax’s control I a project of mine, but even though his original code was sufficient to build a simple demo of the control, I wanted to create a nice templateable custom control with all the behaviour we need. As it turns out, doing that is not trivial, especially for a WPF Newbie like me.

The learning curve was really steep, but I really learned a lot about WPF, custom controls and control authoring this way. The delay I’m having is really huge, so this is really a post about an upcoming article. However, since the control is now almost finished, here are some screenshots and the xaml code that the user will need to create the control:

MenuKiller screen shot

  1. <mk:MenuKiller VerticalAlignment="Center">
  2.   <mk:MenuKillerItem>
  3.     <mk:MenuKillerItem.Header>
  4.       <Image Width="64" Source="….png"/>
  5.     </mk:MenuKillerItem.Header>
  6.  
  7.     <mk:MenuKillerItem>
  8.       <mk:MenuKillerItem.Header>
  9.         <Image Width="32" Source="….png"/>
  10.       </mk:MenuKillerItem.Header>
  11.     </mk:MenuKillerItem>
  12.    
  13.     <mk:MenuKillerItem>
  14.       <mk:MenuKillerItem.Header>
  15.         <Image Width="32" Source="….png"/>
  16.       </mk:MenuKillerItem.Header>
  17.     </mk:MenuKillerItem>
  18.  
  19.     <mk:MenuKillerItem>
  20.       <mk:MenuKillerItem.Header>
  21.         <Image Width="32" Source="….png"/>
  22.       </mk:MenuKillerItem.Header>
  23.     </mk:MenuKillerItem>
  24.  
  25.     <mk:MenuKillerItem>
  26.       <mk:MenuKillerItem.Header>
  27.         <Image Width="32" Source="….png"/>
  28.       </mk:MenuKillerItem.Header>
  29.     </mk:MenuKillerItem>
  30.   </mk:MenuKillerItem>
  31. </mk:MenuKiller>

As you can see, using the control is really simple. The cool icons, by the way, are from http://wearwolfaa.deviantart.com/art/23-PNG-Vista-Style-Icons-74510840.

Stay tuned - I will be busy on The CodeProject the next days, where I will certainly write an article about this control!

My current solution involves a custom panel, an overridden tree-view and tree view item, a rather complex default-theme, Custom Commands, 2 “PART_”-Controls within the template that can be overridden as well as a set of custom converters. This is not final, however, because some of these items currently don’t do a thin.

Still, everything is a little simplified, since I wanted to support the probable and important cases first, rather than the offbeat scenario. 

I also had a very long and important customer meeting yesterday where I presented this control in a demo app. Now people generally try to stick to what they know, but while my customer argued that the ‘old way’ should still be available to end-users, he also showed a lot of interest in this new kind of user experience.

If you want to read about Differentiated UX further, I suggest these resources:

Sample Applications: Familiy.Show, Woodgrove Finance Application and Cine.View.

Posts and Articles: Differentiated UX by Dax Pandhi, Differentiated UX by Brian Noyes

My dearest thanks to Dax, who has encouraged me to build this control and has always been a valuable brainstorm victim ;-) Cheers Dax!

Chris

Krzysztof Cwalina on API Design

April 6, 2008 – 10:52 pm

This is a rather old one (dated June 1st 2007), but I feel this one deserves it: A three-hour webcast by FxCop creator Krzysztof Cwalina who now works at Microsoft on the design of APIs, a little post mortem on the development of the .NET Framework, etc.

You can download the not-so-small file here:

http://blogs.msdn.com/kcwalina/archive/2007/06/01/FDGLecture.aspx

 

While three hours seem to be excessive, this is a really interesting webcast with a very high information density… Have fun!

New Prism Drop!

April 3, 2008 – 5:35 pm

Again, there is a new drop for the Prism Reference Implementation. Get it here:

http://www.codeplex.com/prism/Release/ProjectReleases.aspx?ReleaseId=12226

At the current release intervals, it’s hard to keep up ;-)