【问题标题】:Dynamic menu items with dynamic shortcut keys using c# wpf使用 c# wpf 使用动态快捷键的动态菜单项
【发布时间】:2023-04-10 21:38:02
【问题描述】:

关于 c# wpf 的问题

我正在使用 c# WPF 创建一个 Windows 应用程序,我正在使用来自数据库的 (c#) 菜单数据背后的代码的菜单控件在主窗口上创建菜单。我的数据库中还有一张用于键盘快捷键数据的表。所以,我想在相应的菜单项中分配那个快捷键值。我们怎样才能做到这一点?

简而言之,如何为动态菜单项分配动态快捷键值?

例如, 菜单是_Transactions 菜单项是 _Sales 子菜单项是 _Add 子菜单项是_Display

数据库中的快捷键数据 事务菜单的键值是 Alt + T

示例代码是...

try
        {
            menuContainer.Children.Clear();
            System.Windows.Controls.Menu topMenu = new 
System.Windows.Controls.Menu();
            DataTable dtMainMenu = Global.DatabaseMethod.GetMenuData();
            DataTable dtSubMenu = null;
            DataTable dtChildMenu = null;
            DataTable dtSubChildMenu = null;
            if (dtMainMenu != null && dtMainMenu.Rows.Count > 0)
            {
                MenuItem parentMenuItem = null;
                MenuItem subMenuItem = null;
                MenuItem childMenuItem = null;
                MenuItem subchildMenuItem = null;
                DataRow[] dataRow = null;
                dtMainMenu.DefaultView.Sort = "SequenceNumber ASC";
                dtMainMenu = dtMainMenu.DefaultView.ToTable();
                foreach (DataRow parentMenuRow in dtMainMenu.Rows)
                {
                    parentMenuItem = new MenuItem();
                    parentMenuItem.Tag = 
parentMenuRow[ColumnNameConstants.Slug].ToString() + "~" + 
parentMenuRow[ColumnNameConstants.ID].ToString();
                    parentMenuItem.Header = 
parentMenuRow[ColumnNameConstants.MenuName].ToString();
                    dataRow = Global.dtUserRole.Select("((MenuId='" + 
Convert.ToInt32(parentMenuRow[ColumnNameConstants.ID]) + "' AND 
SubMenuId=0 AND ChildMenuId=0) OR (MenuId='" + 
Convert.ToInt32(parentMenuRow[ColumnNameConstants.ID]) + "'))");
                    parentMenuItem.PreviewMouseDown += 
MenuItem_PreviewMouseDown;
                    parentMenuItem.PreviewKeyDown += 
MenuItem_PreviewKeyDown;
                    if (dataRow.Length > 0)
                    {
                        topMenu.Items.Add(parentMenuItem);
                        if (!Convert.ToBoolean(dataRow[dataRow.Length - 
1][ColumnNameConstants.VisibleRole]))
                        {
                            parentMenuItem.Visibility = 
Visibility.Collapsed;
                        }
                    }
                    else
                    {
                        topMenu.Items.Add(parentMenuItem);
                        parentMenuItem.Visibility = 
Visibility.Collapsed;
                    }
                }
                topMenu.Background = Brushes.Transparent;
                topMenu.Foreground = Brushes.White;
                topMenu.VerticalAlignment = VerticalAlignment.Center;
                menuContainer.Children.Add(topMenu);
            }
        }
        catch (Exception ex)
        {
         
        }

【问题讨论】:

  • 你能给我们展示一些创建这些菜单项的代码吗?那么我们可能更容易准确地告诉你应该做什么。

标签: c# wpf menu keyboard-shortcuts


【解决方案1】:

这应该让你更接近一点。

    <Window x:Class="WpfApp11.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"
            xmlns:local="clr-namespace:WpfApp11"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
        <Grid>
            <Menu x:Name="mainmenu" VerticalAlignment="Top"/>
        </Grid>
    </Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

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

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            MenuItem filemenu = new MenuItem();
            filemenu.Header = "_File";

            MenuItem menuitem1 = new MenuItem();
            menuitem1.Header = "Item _1";
            menuitem1.InputGestureText = "Ctrl+A";
            //menuitem1.Click += menuitem_Click;
            //menuitem1.Tag = "slug1~id1"; //parentMenuRow[ColumnNameConstants.Slug].ToString() + "~" + parentMenuRow[ColumnNameConstants.ID].ToString();
            menuitem1.CommandParameter = "slug1~id1"; //parentMenuRow[ColumnNameConstants.Slug].ToString() + "~" + parentMenuRow[ColumnNameConstants.ID].ToString();
            menuitem1.Command = this;

            MenuItem menuitem2 = new MenuItem();
            menuitem2.Header = "Item _2";
            menuitem2.InputGestureText = "Ctrl+B";
            //menuitem2.Click += menuitem_Click;
            //menuitem2.Tag = "slug2~id2"; //parentMenuRow[ColumnNameConstants.Slug].ToString() + "~" + parentMenuRow[ColumnNameConstants.ID].ToString();
            menuitem2.CommandParameter = "slug2~id2"; //parentMenuRow[ColumnNameConstants.Slug].ToString() + "~" + parentMenuRow[ColumnNameConstants.ID].ToString();
            menuitem2.Command = this;

            filemenu.Items.Add(menuitem1);
            filemenu.Items.Add(menuitem2);

            mainmenu.Items.Add(filemenu);

            this.InputBindings.Add(new KeyBinding(this, Key.A, ModifierKeys.Control) { Command = this, CommandParameter = "slug1~id1" });
            this.InputBindings.Add(new KeyBinding(this, Key.B, ModifierKeys.Control) { Command = this, CommandParameter = "slug2~id2" });
        }

        //----------------------------------------------------------------------

        private void menuitem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menu = sender as MenuItem;

            if (menu != null)
            { 
                MessageBox.Show(menu.Tag as string);

                e.Handled = true;
            }
        }

        //----------------------------------------------------------------------

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            string item = parameter as string;

            if (item == "slug1~id1")
            { 
                // Decide if command should be enabled of not

                return true;
            }

            if (item == "slug2~id2")
            {
                // Decide if command should be enabled of not

                return true;
            }

            return false;
        }

        public void Execute(object parameter)
        {
            ExecuteItem(parameter);
        }

        //----------------------------------------------------------------------

        private void ExecuteItem(object parameter)
        {
            string item = parameter as string;

            if (item != null)
            {
                MessageBox.Show(item);
            }
        }
    }
}

【讨论】:

  • 感谢CSmith的回复
  • 我无法实现 ICommand 接口,因为许多代码都包含“this”,因此会引发问题。请帮我解决这个问题。
  • 错误 CS0263:'MainWindow' 的部分声明不得指定不同的基类
  • 您使用的是 NET Framework 4,还是使用 NET 5 或 6?我使用了 NET 框架。您需要做的就是在某些东西上实现 ICommand。 “this”引用,用于访问“Window”对象,以便可以为快捷键添加输入绑定,并引用“command”。不要有“两个”具有不同基类的 MainWindow 部分类......不要只是复制我所做的并放入你的源代码......因为你可能已经在某个地方有一个 MainWindow 类。
  • 现在工作正常。谢谢 CSmith。
猜你喜欢
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
相关资源
最近更新 更多