Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / WPF
Tip/Trick

WPF Drop Down Menu Button

Rate me:
Please Sign up or sign in to vote.
4.94/5 (14 votes)
5 Oct 2016CPOL1 min read 45.6K   1.4K   12  
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
-- There are no messages in this forum --