【问题标题】:How to make right click Button Context menu in WPF?如何在 WPF 中制作右键单击按钮上下文菜单?
【发布时间】:2017-04-21 16:23:19
【问题描述】:

我正在开发一个 WPF 错误记录应用程序,当用户输入新的连接字符串时,会创建一个连接按钮并在侧边栏上显示为堆叠列表。

我想在这些连接按钮上进行右键单击事件,以显示查看、编辑、删除的按钮上下文菜单。

我的MainWindow.xaml侧边栏网格是这样的,

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="318*" />

        </Grid.ColumnDefinitions>
        <ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
            <StackPanel Name="listConnections" Grid.Column="0" Background="#4682b4" Margin="0,0,0,-0.2" >
            </StackPanel>
        </ScrollViewer>

        </TabControl>
    </Grid> 

我在我的 MainWindow.xaml.cs 中像这样调用Stackpanel listConnections

public MainWindow()
{
    InitializeComponent();

    GetUserData();
    //Button to create new connection
    listConnections.Children.Add(new NewConnectionButton(this));
    this.Closed += new EventHandler(MainWindow_Close);
}

Right-Click event WPF 我试图按照此链接创建右键单击事件,但它不适合我。有人可以帮我吗?

【问题讨论】:

  • 在深入学习使用代码隐藏的 WPF 之前,请考虑学习 MVVM 模式。 WPF 明显更容易与 MVVM 一起使用。但是,如果您以前从未使用过它,那将是一个相当大的心理转变,因此请为学习曲线做好准备。以后你会感谢自己的。
  • 感谢您的提醒。我对 WPF 很陌生,很难理解 .xaml 和 .xaml cs。但现在我只是坚持完成这个最终的 WPF 项目。

标签: c# wpf xaml


【解决方案1】:

我在这里要做的是:

  • 单独创建上下文菜单并将其分配给 UI 上的每个“连接”对象
  • 为每个菜单项处理MenuItem.Click clicks 事件
  • 解析列表中点击的项目并分别处理

MVVM 和所有这些当然都很好,但这种直接的方法至少是一个不错的起点:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <!-- Having CommandParameter is crucial here -->
        <ContextMenu x:Key="contextMenu">
            <MenuItem Header="View"
                      Click="View_OnClick"
                      CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}"/>
            <MenuItem Header="Edit"
                      Click="Edit_OnClick"
                      CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}" />
            <MenuItem Header="Delete"
                      Click="Delete_OnClick"
                      CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}"/>
        </ContextMenu>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="318*" />
        </Grid.ColumnDefinitions>
        <ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
            <StackPanel Name="listConnections" Grid.Column="0" Background="#4682b4" Margin="0,0,0,-0.2" >
                <Button Click="BtnAdd_OnClick">New Connection</Button>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Window>

代码隐藏:

using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication7
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private static Label FindClickedItem(object sender)
        {
            var mi = sender as MenuItem;
            if (mi == null)
            {
                return null;
            }

            var cm = mi.CommandParameter as ContextMenu;
            if (cm == null)
            {
                return null;
            }

            return cm.PlacementTarget as Label;
        }

        private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
        {
            listConnections.Children.Add(new Label
            {
                Content = "New Connection",
                ContextMenu = (ContextMenu)Resources["contextMenu"]
            });
        }

        private void View_OnClick(object sender, RoutedEventArgs e)
        {
            var clickedItem = FindClickedItem(sender);
            if (clickedItem != null)
            {
                MessageBox.Show(" Viewing: " + clickedItem.Content);
            }
        }

        private void Edit_OnClick(object sender, RoutedEventArgs e)
        {
            var clickedItem = FindClickedItem(sender);
            if (clickedItem != null)
            {
                string newName = "Connection edited on " + DateTime.Now.ToLongTimeString();
                string oldName = Convert.ToString(clickedItem.Content);
                clickedItem.Content = newName;
                MessageBox.Show(string.Format("Changed name from '{0}' to '{1}'", oldName, newName));
            }
        }

        private void Delete_OnClick(object sender, RoutedEventArgs e)
        {
            var clickedItem = FindClickedItem(sender);
            if (clickedItem != null)
            {
                string oldName = Convert.ToString(clickedItem.Content);
                listConnections.Children.Remove(clickedItem);
                MessageBox.Show(string.Format("Removed '{0}'", oldName));
            }
        }
    }
}

这就是它的样子:

希望对你有帮助

【讨论】:

【解决方案2】:

你应该在按钮的资源中放置一个上下文菜单,像这样

<NewConnectionButton.Resources>
    <ContextMenu x:Key="connectionButtonContext"  StaysOpen="true">
        <MenuItem Header="Add" Click="InternalAddButton_Click"/>
        <MenuItem Header="Delete" Click="InternalDeleteButton_Click"/>
        <MenuItem Header="Edit" Click="InternalEditButton_Click"/>
    </ContextMenu>
</NewConnectionButton.Resources>

此代码应在NewConnectionButton UserControl 内。在 UserControl C# 代码中,订阅这些事件并公开它们 (InternalAddButton_ClickInternalDeleteButton_ClickInternalEditButton_Click)谁使用按钮。然后,在您的MainWindow 中订阅它们。

【讨论】:

    猜你喜欢
    • 2011-10-10
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多