How to open a popup menu when a button is clicked?

后端 未结 4 1992
时光取名叫无心
时光取名叫无心 2020-12-30 01:14

I have a button with an Image as its content in a toolbar. I would like this button to open a menu beneath it when clicked. How?


                     


        
相关标签:
4条回答
  • 2020-12-30 02:02

    i found this two solutions after searching for it:

    1) Split Button in WPF

    2) DropDownButtons in WPF

    the second solution is my favorit (source taken from the website by Andrew Wilkinson)

    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)this.GetValue(DropDownProperty); }
        set { this.SetValue(DropDownProperty, value); }
      }
    
      // *** Overridden Methods *** 
    
      protected override void OnClick() {
        if (this.DropDown != null) {
          // If there is a drop-down assigned to this button, then position and display it 
    
          this.DropDown.PlacementTarget = this;
          this.DropDown.Placement = PlacementMode.Bottom;
    
          this.DropDown.IsOpen = true;
        }
      }
    }
    

    usage

    <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>
    

    hope that helps you...

    0 讨论(0)
  • 2020-12-30 02:03

    There are lots of ways to get this done and you might consider this approach...

    <ToolBar DockPanel.Dock="Top">
        <MenuItem IsSubmenuOpen="{Binding SomeProperty}">
            <MenuItem.Header>
                <Button Height="28">
                    <Button.Content>
                        <Image Source="---your image---"></Image>
                    </Button.Content>
                </Button>
            </MenuItem.Header>
            <Menu>
                <MenuItem Header="Do this" />
                <MenuItem Header="Do that"/>
            </Menu>
        </MenuItem>
    </ToolBar>
    

    This wraps your button into a MenuItem that has a submenu. As shown here, the MenuItem property called IsSubMenuOpen is bound to a notifying property of type bool in your ViewModel called SomeProperty.

    You would have to have your ViewModel toggle this property depending upon what you are actually trying to do. You may want to consider making your button a toggle button so as to facilitate closing the submenu, otherwise you'll have to wire up additional behaviour in your ViewModel.

    0 讨论(0)
  • 2020-12-30 02:04

    If you have the luxury of targeting .NET 4 or newer, the new Ribbon library has a RibbonMenuButton that can do this. In 4.5 it is as easy as referencing System.Windows.Controls.Ribbon in your project:

    <RibbonMenuButton x:Name="ExampleMenu" SmallImageSource="/Images/Example.png">
        <RibbonMenuItem x:Name="ExampleMenuItem" Header="Save" />
    </RibbonMenuButton>
    
    0 讨论(0)
  • 2020-12-30 02:07

    Instead of using a subclassed Button, you can use Attached Properties or a Behavior to implement the drop down button functionality, for a more WPF-like approach and so you don't impact the button style:

    using System.Windows.Interactivity;
    
    public class DropDownButtonBehavior : Behavior<Button>
    {
        private bool isContextMenuOpen;
    
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.AddHandler(Button.ClickEvent, new RoutedEventHandler(AssociatedObject_Click), true);
        }
    
        void AssociatedObject_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Button source = sender as Button;
            if (source != null && source.ContextMenu != null)
            {
                if (!isContextMenuOpen)
                {
                    // Add handler to detect when the ContextMenu closes
                    source.ContextMenu.AddHandler(ContextMenu.ClosedEvent, new RoutedEventHandler(ContextMenu_Closed), true);
                    // If there is a drop-down assigned to this button, then position and display it 
                    source.ContextMenu.PlacementTarget = source;
                    source.ContextMenu.Placement = PlacementMode.Bottom;
                    source.ContextMenu.IsOpen = true;
                    isContextMenuOpen = true;
                }
            }            
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.RemoveHandler(Button.ClickEvent, new RoutedEventHandler(AssociatedObject_Click));
        }
    
        void ContextMenu_Closed(object sender, RoutedEventArgs e)
        {
            isContextMenuOpen = false;
            var contextMenu = sender as ContextMenu;
            if (contextMenu != null)
            {
                contextMenu.RemoveHandler(ContextMenu.ClosedEvent, new RoutedEventHandler(ContextMenu_Closed));
            }
        }
    }
    

    Usage:

    <!-- NOTE: xmlns:i="schemas.microsoft.com/expression/2010/interactivity‌​" -->
    <Button>
        <i:Interaction.Behaviors>
            <local:DropDownButtonBehavior/>
        </i:Interaction.Behaviors>
        <Button.Content>
            <StackPanel Orientation="Horizontal">
                <Image Source="/DropDownButtonExample;component/Assets/add.png" SnapsToDevicePixels="True" Height="16" Width="16" />
                <TextBlock Text="Add"/>
                <Separator Margin="2,0">
                    <Separator.LayoutTransform>
                        <TransformGroup>
                            <TransformGroup.Children>
                                <TransformCollection>
                                    <RotateTransform Angle="90"/>
                                </TransformCollection>
                            </TransformGroup.Children>
                        </TransformGroup>
                    </Separator.LayoutTransform>
                </Separator>
                <Path Margin="2" VerticalAlignment="Center" Width="6" Fill="#FF527DB5" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
            </StackPanel>
        </Button.Content>
        <Button.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Attribute"/>
                <MenuItem Header="Setting"/>
                <Separator/>
                <MenuItem Header="Property"/>
            </ContextMenu>
        </Button.ContextMenu>
    </Button>
    

    Current gist source and example here.

    0 讨论(0)
提交回复
热议问题