Jerry Nixon on Windows: XAML: How to add ItemsSource to the Windows 8.1 MenuFlyout

Jerry Nixon's blog

Monday, December 2, 2013

XAML: How to add ItemsSource to the Windows 8.1 MenuFlyout

imageWith Windows 8.0, Flyout options for developers were constrained to 1) custom development to get what you wanted or 2) using my Settings and Flyout helpers to shortcut the custom work, or using Tim’s Callisto Flyout to do it for you. They all worked, but none was ideal.

With Windows 8.1 there are several new Flyout options for developers. There’s very little for need custom development because the platform Flyout is very flexible and prescriptive.

Windows 8.1 Flyouts

The Flyout class represents a control that displays lightweight UI that is either information, or requires user interaction. Unlike a dialog, a Flyout can be light dismissed by clicking or tapping off of it. The Flyout could contain a single element and, as a bonus, could be attached to a button.

image

The FlyoutBase.Placement property gets or sets the default placement to be used for the flyout, in relation to its placement target. The FlyoutPlacementMode enumeration defines constants that specify the preferred location for positioning a FlyoutBase derived control relative to a visual element. Possible values are: (Top, Bottom, Left, Right, Full – center screen).

The MenuFlyout class represents a flyout that displays a menu of commands. The MenuFlyout has an Items property which is the collection menu elements, including: MenuFlyoutItem (the button), MenuFlyoutSeparator, and ToggleMenuFlyoutItem (the toggle button).

image

Those two controls solved the button-interaction scenarios that caused significant custom development in Windows 8.0. In all reality, it was Callisto that saved the day until Windows 8.1 came with an out-of-the box solution. But in addition, there was one more flyout needed!

The SettingsFlyout class represents a control that provides in-context access to settings that affect the current app. It is (Windows 8.1) the go-t- solution for an About box, an Options dialog, and anything else that might leverage the Settings charm and the right edge.

image

The Problem

The MenuFlyout is a simple list (Items) of MenuFlyoutItemBase that, unfortunately, is not observable. As a result, this collection cannot be modified at runtime. As a result, the menu items present cannot be dynamically added and removed using standard MVVM techniques. Instead, code-behind directly addressing the control’s collection is required.

image

The Solution

I admit, this might be an edge case. And, I admit that my solution may undermine the inherent accessibility and keyboarding features of the MenuFlyout. That being said, if your UI requires dynamic MenuFlyout and you want to create those items dynamically in your view model, this is how you do it.

image

In the end, the solution is two attached properties on a generic Flyout. Setting the ItemsSource and the ItemTemplate properties gives developers the ultimate in flexibility. The resulting UI looks however the developer wants, and does or doesn’t have a FlyoutMenuItem depending on their template.

Get all the code here.

Your XAML might look like this:

image

What? No gravy?

But what if you really wanted to use a MenuFlyout? Is that still an option? Of course it is. In order to accomplish this requirement, all you need to do is listen for the activity of the ItemsSource and constrain it to an ObservableCollection type. But there is one caveat. How do you bind the correct Text or Command to the MenuItem? You really can’t without falling back to convention.

Option 1: You could assume everything bound to ItemsSource has a Text and Command property. Then you could simply update the Items collection of the MenuFlyout with a new item. In your application this might be fine, since you know your own code.

Option 2: You could bind to a collection of MenuItems in your view model. This requires your view model to instantiate XAML controls. Again, in your application this might be fine. But some people might take issue that creating UI controls in your view model is a slippery slope.

So maybe it’s not so easy if you want to use a MenuFlyout after all. As the developer of your app, these are design calls you will need to make. There are benefits and trade-offs that only you can ultimately weigh.

Conclusion

In the end, you can certainly enable repeaters inside a Flyout. And this simple solution is a great lesson in attached properties and the ability for XAML’s flexibility to do whatever you can dream up. You might be wondering, is this any different that embedding an ItemsControl in the Flyout? And, the answer would be no – except for the benefit of reused code.

Take-away tip: ‘propa’ is the built-in Visual Studio snippet for attached properties.

Best of luck!