Sunday, October 29, 2006

DropDownButtons in WPF

Whilst Windows Presentation Foundation (WPF) provides good support for menus, one omission is a drop-down button. By this I mean a button, that when clicked will result in a menu dropping down from the control.

So I started to write my own. Easy I thought, just style a MenuItem to look like a button. Well, this doesn't work as the MenuItem control will only work if it is a child of a Menu control. I could just wrap all my DropDownButtons in Menus, but that becomes a little messy wrapping everything in extra menus. I tried a number of other approaches, none of which worked as I would like.


This was several months ago. Recently however I was informed of a couple of related blog articles at Sheva's Techspace and Lester's piece on WPF. In particular I liked Lester's approach. This is to use the Button's ContextMenu to apply add a context menu, and then to use code to open this on a left mouse click. A simple solution that works well. But what if I wanted to have a real context-menu too?


Solution: Well, in fact ContextMenu doesn't need to be attached to a control to work. All you need to do is create a new ContextMenu object, add your MenuItems, and set IsOpen to true. So I put together the control as below.



public class DropDownButton : ToggleButton
{
// *** Dependency Properties ***


public static readonly DependencyProperty DropDownProperty = DependencyProperty.Register("DropDown", typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null));

// *** Constructors ***

public DropDownButton()
{
// Bind the ToogleButton.IsChecked property to the drop-down's IsOpen property

Binding binding = new Binding("DropDown.IsOpen");
binding.Source = this;
this.SetBinding(IsCheckedProperty, binding);
}

// *** Properties ***

public ContextMenu DropDown
{
get
{
return (ContextMenu)GetValue(DropDownProperty);
}
set
{
SetValue(DropDownProperty, value);
}
}

// *** Overridden Methods ***

protected override void OnClick()
{
if (DropDown != null)
{
// If there is a drop-down assigned to this button, then position and display it

DropDown.PlacementTarget = this;
DropDown.Placement = PlacementMode.Bottom;

DropDown.IsOpen = true;
}
}
}


This control derives directly from ToggleButton so we inherit the full behavior and styling of a button. We then provide a DropDown dependency property that takes a ContextMenu to show for the drop-down. In the OnClick event we simply position the menu under the control, and open it by setting IsOpen to true. Finally to tidy up, we bind the ToggleButton's IsChecked property to the drop-down menu's IsOpen property to ensure that these are synchronized.


To use this in your own code you simply use,



<ctrl:DropDownButton Content="Drop-Down">
<ctrl:DropDownButton.DropDown>
<ContextMenu>
<MenuItem Header="Item 1"/>
<MenuItem Header="Item 2"/>
<MenuItem Header="Item 3"/>
</ContextMenu>
</ctrl:DropDownButton.DropDown>
</ctrl:DropDownButton>



Technorati tags: , ,

An Office 2007 style Ribbon in WPF?

For a while now I have been working on reproducing an Office 2007 Ribbon style application in Windows Presentation Foundation (WPF). This includes not just the ribbon itself, but also the full window chrome.

Whilst the official documentation has been in progress, blogs have been a great alternative source of information. However now I thought would be a good time to start my own blog discussing, amongst other things, how I am writing my Ribbon control.

Hope over the coming months you enjoy my posts and find something of interest to your own development needs. I'll focus on some of the issues that I have encountered, and will post some images of the fully working Ribbon control.

Technorati tags: ,