The blog of dlaa.me

SplitButtoning hairs [Two fixes for my Silverlight SplitButton/MenuButton implementation - and true WPF support]

One of my ContextMenu test cases for the April '10 release of the Silverlight Toolkit (click here for the full write-up) was to implement a quick "split button" control for Silverlight using Button and ContextMenu. In that post, I cautioned that my goal at the time was to do some scenario testing, not to build the best SplitButton control ever. However, what I came up with seemed to work pretty well in practice and I figured folks could probably use the code mostly as-is.

And it seems like they did - because I got two bug reports in that post's comments section! :)

SplitButton and MenuButton

 

Let me address them in reverse order:

The position of the ContextMenu was wrong when the browser is zoomed: True enough - though I'm going to ask for a bit of leniency here because the cause of the misalignment is actually a bug in Silverlight (which I've already reported). It seems the results of a call to element.TransformToVisual(Application.Current.RootVisual) or element.TransformToVisual(null) are not consistent for elements that are vs. are not inside a Popup control when the browser is zoomed (in or out). As a result, the SplitButton code to position the menu got inconsistent data and was unable to place the menu correctly. I've tweaked the code slightly to accommodate the underlying issue and now the menu is properly aligned at any zoom setting.

While I was at it, I figured it might be nice if the menu moved around with the SplitButton as the user resized the browser or changed the zoom while the menu was displayed. This is admittedly an edge case, but it's easy enough to handle by hooking the LayoutUpdated event while the menu is displayed (and only while it's displayed!), so I did that and now the menu sticks to the button and refuses to be shaken off. :)

The code didn't work on WPF: I had a footnote claiming my Silverlight implementation should work on WPF as well, though I hadn't tried it myself. It turns out that statement is mostly true - except for the positioning logic which bumps into an subtle API incompatibility with the TransformToVisual method. (Noticing a pattern here?) In the process of getting things working for WPF, I realized the code to position the menu could be simplified somewhat with the (WPF-only) TranslatePoint method. Therefore, the actual positioning logic is a tad different across the two platforms ("a tad" == 4 lines of code) while everything else stays the same. This time when I claim SplitButton and MenuButton work on WPF, it's because I've tried it. :)

In fact, I've added a new, WPF-specific assembly (SplitButtonWpf) and demo (SplitButtonWpfSample) to the sample code associated with this post. Which means there is a dedicated assembly containing SplitButton and MenuButton for both platforms as well as a separate sample application for each!

 

[Click here to download the complete Silverlight/WPF source code for SplitButton/MenuButton and the sample application shown above.]

 

With those changes in place (and an unrelated key handling tweak for WPF), I feel even better about the prospects of using SplitButton and MenuButton in a real application. Naturally, if something else comes up, please let me know. Otherwise, I hope you find it useful!