Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Drop Down Menu Button

0.00/5 (No votes)
5 Oct 2016 1  
Presents and implementation of a control that can be pressed to bring up a Menu.

Introduction

There was a need to have a Button for adding elements to an ItemsControl, but there were several different types that could be added. Adding a Button for each would have created a lot of controls, and the other option of adding a ComboBox to specify the type to be added seemed even worse (this was the previous solution). Thus a Button that brought up a number of selections seemed to be obvious. Then the question was what to use, and a Menu control seemed to be the best solution

Implementation

The DropDownButton inherits from the ToggleButton:

C#
public class DropDownButton : ToggleButton
{
   public DropDownButton()
    {
        // Bind the ToogleButton.IsChecked property to the drop-down's IsOpen property
        Binding binding = new Binding("Menu.IsOpen");
        binding.Source = this;
        this.SetBinding(IsCheckedProperty, binding);
        DataContextChanged += (sender, args) =>
        {
            if (Menu != null)
                Menu.DataContext = DataContext;
        };
    }

    // *** Properties ***
    public ContextMenu Menu
    {
        get { return (ContextMenu)GetValue(MenuProperty); }
        set { SetValue(MenuProperty, value); }
    }
    public static readonly DependencyProperty MenuProperty = DependencyProperty.Register("Menu",
        typeof(ContextMenu), typeof(DropDownButton), new UIPropertyMetadata(null, OnMenuChanged));

    private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dropDownButton = (DropDownButton)d;
        var contextMenu = (ContextMenu)e.NewValue;
        contextMenu.DataContext = dropDownButton.DataContext;
    }

    protected override void OnClick()
    {
        if (Menu != null)
        {
            Menu.PlacementTarget = this;
            Menu.Placement = PlacementMode.Bottom;
            Menu.IsOpen = true;
        }
    }

It adds one DependencyProperty for the Menu, which is type ContextMenu,

The first thing that needs to be done is to make the ContextMenu visible when the ToggleButton is in the IsChecked state. The override on the OnClick method does this, and also sets the Placement.

The other necessary thing is to set the DataContext of the ContextMenu. Unfortunately, the DataContext of the ToggleButton is not set to be the DataContext of any of this type of embedded control. Therefore, whenever the Menu DependencyProperty or DataContext for the ToggleButton is changed, the DataContext of the ToggleButton is applied to the DataContext of the Menu. One is done with the change of the Menu DependencyProperty, the other is done by handling the DataContextChanged of the ToggleButton.

Using the Control

The use of the Control is pretty straight forward. It us just like a ToggleButton, but there is an additional DependencyProperty that needs to be set to the instance of a ContextMenu as shown below.

XML
<local:DropDownButton Margin="0,4"
                      HorizontalAlignment="Center"
                      VerticalAlignment="Center"
                      Style="{StaticResource EllipseToggleButtonStyle}">
    <ContentControl ContentTemplate="{StaticResource PlusIcon}" />
    <local:DropDownButton.Menu>
        <ContextMenu>
            <MenuItem Command="{Binding AddCommand}"
                      CommandParameter="{Binding}"
                      Header="Add" />
            <MenuItem Command="{Binding DeleteCommand}"
                      CommandParameter="{Binding}"
                      Header="Delete" />
            <MenuItem Command="{Binding MoveCommand}"
                      CommandParameter="{Binding}"
                      Header="Move" />
        </ContextMenu>
    </local:DropDownButton.Menu>
</local:DropDownButton>

   

History

  • 2016/10/05: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here