Подтвердить что ты не робот

Как открыть всплывающее меню при нажатии кнопки?

У меня есть кнопка с изображением в виде содержимого на панели инструментов. Я бы хотел, чтобы эта кнопка открывала меню под ним при нажатии. Как?

<Toolbar>
            <Button>
                <Button.Content>
                    <Image  Source="../Resources/help.png"></Image>
                </Button.Content>
            </Button>
</Toolbar>

Спасибо!!

4b9b3361

Ответ 1

Вместо использования Button с подклассом вы можете использовать Attached Properties или Behavior, чтобы реализовать функциональность кнопки выпадающего списка, для более WPF-подобного подхода и поэтому вы не влияете на стиль кнопки:

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));
        }
    }
}

Использование:

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

Текущий источник источника и пример здесь.

Ответ 2

Я нашел эти два решения после поиска:

1) Кнопка разделения в WPF

2) DropDownButtons в WPF

второе решение - моя позиция (источник, взятый с веб-сайта Эндрю Уилкинсона)

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

Использование

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

надеюсь, что вам поможет...

Ответ 3

Если у вас есть таргетинг на .NET 4 или новее, новая библиотека Ribbon имеет RibbonMenuButton, которая может это сделать. В 4.5 это так же просто, как ссылка на System.Windows.Controls.Ribbon в вашем проекте:

<RibbonMenuButton x:Name="ExampleMenu" SmallImageSource="/Images/Example.png">
    <RibbonMenuItem x:Name="ExampleMenuItem" Header="Save" />
</RibbonMenuButton>

Ответ 4

Есть много способов сделать это, и вы можете рассмотреть этот подход...

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

Это завершает вашу кнопку в MenuItem, в котором есть подменю. Как показано здесь, свойство MenuItem, называемое IsSubMenuOpen, связано с уведомляющим свойством типа bool в вашей ViewModel под названием SomeProperty.

Вам нужно было бы, чтобы ваш ViewModel переключил это свойство в зависимости от того, что вы на самом деле пытаетесь сделать. Вы можете подумать о том, чтобы сделать вашу кнопку кнопкой переключения, чтобы облегчить закрытие подменю, иначе вам придется подключить дополнительное поведение в вашей ViewModel.

Ответ 5

или использовать дизайн материала, это приятно lib

           <materialDesign:PopupBox HorizontalAlignment="Right" Margin="10"
                                 PlacementMode="BottomAndAlignRightEdges"
                                 StaysOpen="False" Foreground="White">
                <StackPanel Width="150">
                    <Button Content="Account"/>
                    <Button Content="Add account"/>
                    <Separator />
                    <Button Content="Logout" Click="logout_button_click"/>
                </StackPanel>

            </materialDesign:PopupBox>