Prism 10933

by Christoph Menge in Software

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.

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags:

Protected: A MenuKiller Sample Application

by Christoph Menge in Software

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


Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , , ,

ICommand.CanExecute() and NullReferenceException

by Christoph Menge in .NET

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…

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , , ,

On UIElement.Opacity and the Removal of Storyboards

by Christoph Menge in Software

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:

<!-- exact storyboard omitted for clarity -->
<Trigger Property="IsMouseOver" SourceName="contentPresenter" Value="True">
  <Trigger.EnterActions>
    <BeginStoryboard x:Name="MouseOver_BeginStoryboard"
                     Storyboard="{StaticResource MouseOver}"/>
  </Trigger.EnterActions>
  <Trigger.ExitActions>
    <BeginStoryboard x:Name="MouseOut_BeginStoryboard"
                     Storyboard="{StaticResource MouseOut}"/>
  </Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed"  Value="True">
  <Trigger.EnterActions>
    <BeginStoryboard x:Name="PressedOn_BeginStoryboard"
                     Storyboard="{StaticResource PressedOn}"/>
  </Trigger.EnterActions>
  <Trigger.ExitActions>
    <BeginStoryboard x:Name="PressedOff_BeginStoryboard"
                     Storyboard="{StaticResource PressedOff}"/>
  </Trigger.ExitActions>
</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:

<Trigger Property="IsMouseOver" SourceName="contentPresenter" Value="True">
  <Trigger.EnterActions>
    <RemoveStoryboard BeginStoryboardName="PressedOff_BeginStoryboard" />
    <BeginStoryboard x:Name="MouseOver_BeginStoryboard"
                     Storyboard="{StaticResource MouseOver}"/>
  </Trigger.EnterActions>
  <Trigger.ExitActions>
    <RemoveStoryboard BeginStoryboardName="PressedOff_BeginStoryboard" />
    <BeginStoryboard x:Name="MouseOut_BeginStoryboard"
                     Storyboard="{StaticResource MouseOut}"/>
  </Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed"  Value="True">
  <Trigger.EnterActions>
    <BeginStoryboard x:Name="PressedOn_BeginStoryboard"
                     Storyboard="{StaticResource PressedOn}"/>
  </Trigger.EnterActions>
  <Trigger.ExitActions>
    <BeginStoryboard x:Name="PressedOff_BeginStoryboard"
                     Storyboard="{StaticResource PressedOff}"/>
  </Trigger.ExitActions>
</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.

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: ,

Applying ItemContainerStyle Recursively

by Christoph Menge in Software

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:

<Style x:Key="MKItemStyle" TargetType="{x:Type local:MenuKillerItem}">
    <Setter Property="Template" Value="{StaticResource MenuKillerItemTemplate}"/>
    <Setter Property="ItemContainerStyle" Value="{DynamicResource MKItemStyle}"/>
</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:

<!-- This Style redefines the ControlTemplate used by TreeViewItems and
       also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem">
  [...]
</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?

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , ,

The MenuKiller Control – Differentiated UX

by Christoph Menge in Software

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

<mk:MenuKiller VerticalAlignment="Center">
  <mk:MenuKillerItem>
    <mk:MenuKillerItem.Header>
      <Image Width="64" Source="....png"/>
    </mk:MenuKillerItem.Header>

    <mk:MenuKillerItem>
      <mk:MenuKillerItem.Header>
        <Image Width="32" Source="....png"/>
      </mk:MenuKillerItem.Header>
    </mk:MenuKillerItem>

    <mk:MenuKillerItem>
      <mk:MenuKillerItem.Header>
        <Image Width="32" Source="....png"/>
      </mk:MenuKillerItem.Header>
    </mk:MenuKillerItem>

    <mk:MenuKillerItem>
      <mk:MenuKillerItem.Header>
        <Image Width="32" Source="....png"/>
      </mk:MenuKillerItem.Header>
    </mk:MenuKillerItem>

    <mk:MenuKillerItem>
      <mk:MenuKillerItem.Header>
        <Image Width="32" Source="....png"/>
      </mk:MenuKillerItem.Header>
    </mk:MenuKillerItem>
  </mk:MenuKillerItem>
</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

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , , , ,

Krzysztof Cwalina on API Design

by Christoph Menge in Software

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!

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , ,

New Prism Drop!

by Christoph Menge in .NET

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 ;-)

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , ,

Custom DependencyProperties and “Auto”

by Christoph Menge in Software

While implementing a little custom control (a radial panel, actually – stay tuned what it’s good for…), I stumbled across a little problem when trying to add automatic behaviour.

Many built-in WPF Controls such as Canvas or Panel allow something like

Width="Auto"

Now, for my control I need something that accepts

AngleSpacing="Auto"
AngleSpacing="<double>"

Of course, accomplishing that is very simple, but it took me some time to find it on MSDN:

In addition to acceptable Double values, this property can also be Double.NaN. This is how you specify auto sizing behavior in code. In XAML you set the value to the string “Auto” (case insensitive) to enable the auto sizing behavior. Auto sizing behavior implies that the element will fill the height available to it. Note however that specific controls frequently supply default values through their default theme styles that will disable the auto sizing behavior unless it is specifically re-enabled.

So, the solution simply is to apply the TypeConverterAttribute as follows:

[TypeConverterAttribute(typeof(LengthConverter))]
public double AngleSpacing
{
    get { return (double)GetValue(AngleSpacingProperty); }
    set { SetValue(AngleSpacingProperty, value); }
}
public static readonly DependencyProperty AngleSpacingProperty =
    DependencyProperty.Register("AngleSpacing",
                                  typeof(double),
                                  typeof(CircularPanel),
                                  new FrameworkPropertyMetadata(45d,
                                  FrameworkPropertyMetadataOptions.AffectsArrange));

This will, however, leave us with a length converter (which is built mainly for Conversion of “pt”, “px”, etc.). There are quite a lot of type coverters available already. For a list, see http://msdn2.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx.  

In my case, I need a custom TypeConverter, which is really simple:

public class DoubleAutoConverter : TypeConverter
{
  public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  {
    if (sourceType == typeof(string) || sourceType == typeof(double))
    {
      return true;
    }

    return base.CanConvertFrom(context, sourceType);
  }

  // Overrides the ConvertFrom method of TypeConverter.
  public override object ConvertFrom(ITypeDescriptorContext context,
     CultureInfo culture, object value)
  {
    if (value is string)
    {
      double dValue;

      if (String.Compare((string)value, "auto", true) == 0)
      {
        dValue = Double.NaN;
      }
      else
      {
        // Don't catch the exception
        dValue = Double.Parse((string)value);
      }

      return dValue;
    }

    // No need to handle the trivial case manually:
    return base.ConvertFrom(context, culture, value);
  }

  public override object ConvertTo(ITypeDescriptorContext context,
     CultureInfo culture, object value, Type destinationType)
  {
    return base.ConvertTo(context, culture, value, destinationType);
  }
}

Now, when the user specifies auto, the property will be set to Double.NaN and can be handled by the control… hopefully

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , , ,

Tao Framework now DPI Aware!

by Christoph Menge in .NET, Software

Huge thanks to Ilmar Kruis for implementing GetDeviceCaps() in the Tao framework! With some small modifications I suggested, one can now easily develop DPI-aware OpenGL applications using C# or .NET in general! Thanks Ilmar!

I will update my article on the CodeProject about OpenGL windows in Vista soon!

See http://www.taoframework.com/

Get the latest version via SVN: https://taoframework.svn.sourceforge.net/svnroot/taoframework

Post to Twitter Post to Delicious Post to Digg Post to Facebook

Tags: , , ,