Click here to Skip to main content
15,867,835 members
Articles / Desktop Programming / WPF

A Pie Menu for WPF

Rate me:
Please Sign up or sign in to vote.
4.78/5 (21 votes)
5 Jan 2013CPOL3 min read 57.6K   2.9K   38   20
Creating a pie menu control for WPF

Introduction

The concept of pie menus have been around for quite some while, and might in certain contexts have some benefits over the standard linear menus. In particular, when large touch screens like the Microsoft PixelSense/Samsung SUR40 become more available, we might expect an increased demand for alternatives to linear menus.

Unfortunately, the .NET framework does not provide a standard pie menu control for WPF. The closest thing is the ElementMenu control of the Surface 2.0 SDK. This article presents a pie menu control for WPF. Because the menu is intended for use in touch enabled applications, it responds to both mouse and touch events.

Using the Code

The PieMenu is used in a fashion similar to the WPF Menu control; a PieMenu may contain any number of PieMenuItems, which again may contain PieMenuItems to arbitrary depth. The labels of the menu items are given by the Header property and their behavior is specified by the Click event or the Command property.

XML
<p:PieMenu x:Name="Menu1">
    <p:PieMenuItem Header="Item 1">
        <p:PieMenuItem Header="Item 1.1" Click="PieMenuItem_Click"/>
        <p:PieMenuItem Header="Item 1.2" Command="NotACommand"/>
        <p:PieMenuItem Header="Item 1.3" />
    </p:PieMenuItem>
    <p:PieMenuItem Header="Item 2">
        <p:PieMenuItem Header="Item 2.1" />
        <p:PieMenuItem Header="Item 2.2" />
    </p:PieMenuItem>
    <p:PieMenuItem Header="Item 3">
        <p:PieMenuItem Header="Item 3.1" />
        <p:PieMenuItem Header="Item 3.2" />
        <p:PieMenuItem Header="Item 3.3" />
        <p:PieMenuItem Header="Item 3.4" />
    </p:PieMenuItem>
</p:PieMenu>

This menu, with only default settings, will look like this (when Item 1.1 is pressed):

Properties common for all UI controls, such as Background, Foreground, FontSize, etc. work as expected, and properties specified in the menu items override properties specified in the menu items. In addition, the PieMenu has several custom properties:

  • SelectedBackground specifies the color of selected menu items (default gray)
  • Radius specifies the radius of the first level of the menu (default 50.0)
  • InnerRadius specifies the radius of the hole in the middle of the menu (default 10.0)
  • Gap specifies the distance between the levels of the menu (default 5.0)
  • SectorGap specifies the distance between menu items at the same level (default 5.0)
  • MenuSector specifies the sector of the circle that the menu will use (default 360.0)
  • Rotation specifies the angle at which the first menu item is placed (default 0.0)
  • RotateText specifies whether the labels of the menu items are rotated to follow the circle (default True)

The PieMenuItem has one custom property: SubMenuSector specifying the sector of the circle that its sub items will occupy (default 120.0).

Thus, we may define a pie menu as follows:

XML
<p:PieMenu x:Name="Menu2"
           Background="Blue"
           SelectedBackground="LightBlue"
           Foreground="White"
           BorderBrush="Red"
           SectorGap="10"
           Gap="10"
           Radius="100"
           InnerRadius="0"
           RotateText="False"
           Rotation="90"
           MenuSector="180">
    <p:PieMenuItem Header="Item 1"
                   BorderThickness="1"
                   SubMenuSector="90">
        <p:PieMenuItem Header="Item 1.1" />
        <p:PieMenuItem Header="Item 1.2" />
        <p:PieMenuItem Header="Item 1.3" />
    </p:PieMenuItem>
    <p:PieMenuItem Header="Item 2"
                   BorderThickness="2"
                   BorderBrush="Green"
                   SubMenuSector="60">
        <p:PieMenuItem Header="Item 2.1" />
        <p:PieMenuItem Header="Item 2.2" />
    </p:PieMenuItem>
    <p:PieMenuItem Header="Item 3"
                   FontFamily="Times New Roman"
                   FontStyle="Italic"
                   FontSize="14"
                   Background="Green"
                   Foreground="Black" >
        <p:PieMenuItem Header="Item 3.1" />
        <p:PieMenuItem Header="Item 3.2" />
        <p:PieMenuItem Header="Item 3.3" />
        <p:PieMenuItem Header="Item 3.4" />
    </p:PieMenuItem>
</p:PieMenu>

This gives the following (not very pretty) menu (when Item 2.1 is pressed):

Points of Interest

The PieMenu class extends ItemsControl while the PieMenuItem class extends HeaderedItemsControl. These general controls give us a lot for free with respect to the management of the menu items.

In the implementation of the menu, the PieMenu class is responsible for the rendering of the full menu as well as maintaining the state of the menu. The alternative approach would be to have each instance of PieMenuItem render itself and maintaining its own state. The benefit of the chosen, centralized, approach is that it makes it easy to calculate the outline and relative placement of the menu items compared to having each menu item figuring out its own outline and placement. The drawback with this approach is that it requires a certain amount of book keeping for remembering which menu items are selected and visible and figuring out which menu item is clicked. In this last respect, a decentralized approach where each menu item keeps track of its own state and handles input events would probably be simpler, even though some messaging between the menu items would be required for maintaining the correct global state of the menu.

Acknowledgements

This code is developed in context of the BRIDGE and DARIUS projects.

History

  • 05 January 2013: Original version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Norway Norway
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questiondeath cycle Pin
Member 1199292329-Dec-16 3:19
Member 1199292329-Dec-16 3:19 
Questiondeath cycle Pin
Member 1199292329-Dec-16 3:19
Member 1199292329-Dec-16 3:19 
AnswerRe: death cycle Pin
CHill6029-Dec-16 3:20
mveCHill6029-Dec-16 3:20 
Questionhow to add a FrameworkElement instead of text Pin
Adam Buchanan31-Mar-15 4:31
Adam Buchanan31-Mar-15 4:31 
SuggestionPieMenuItem hosting a PieMenu Pin
strajkz22-Oct-14 22:05
strajkz22-Oct-14 22:05 
Answer//How draw image inside the menu Pin
aymansaeed873-Aug-14 22:16
aymansaeed873-Aug-14 22:16 
QuestionHow To make last menu item do something ? Pin
aymansaeed873-Aug-14 21:55
aymansaeed873-Aug-14 21:55 
QuestionSilverlight? Pin
Rob Hill0313-Jul-14 5:03
Rob Hill0313-Jul-14 5:03 
QuestionMaths behind the pie menu Pin
Vaanes29-May-14 4:54
Vaanes29-May-14 4:54 
QuestionImage to a MenuItem Pin
Max18092-Apr-14 1:32
Max18092-Apr-14 1:32 
AnswerRe: Image to a MenuItem Pin
aymansaeed873-Aug-14 22:17
aymansaeed873-Aug-14 22:17 
QuestionGood job 2nd Pin
Member 101313094-Jul-13 2:48
Member 101313094-Jul-13 2:48 
AnswerRe: Good job 2nd Pin
Max18092-Apr-14 1:33
Max18092-Apr-14 1:33 
AnswerRe: Good job 2nd Pin
smrm721-Jul-14 3:59
smrm721-Jul-14 3:59 
QuestionGood job Pin
Member 1013130928-Jun-13 5:31
Member 1013130928-Jun-13 5:31 
GeneralMy vote of 5 Pin
LastAngel1231-Apr-13 3:50
LastAngel1231-Apr-13 3:50 
GeneralNo more Meny Bar Pin
6T9Fan9-Jan-13 23:58
6T9Fan9-Jan-13 23:58 
AnswerRe: No more Meny Bar Pin
Mass Soldal Lund10-Jan-13 5:00
Mass Soldal Lund10-Jan-13 5:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.