NotifyIcon 不响应其上下文菜单中的更改

NotifyIcon not responsing to changes in its ContextMenu

我的(仅限无格式系统托盘)程序有一个 NotifyIcon,其 ContextMenu 值必须在程序的 运行 过程中动态更改。程序启动时实例化通知图标对象如下:

notifyIcon = new NotifyIcon()
{
    Icon = new Icon(@"C:\Users\basil\documents\visual studio 2015\Projects\Project Repository\Project Repository\Program Icon.ico"),
    Text = "My Program Name",
    Visible = false // Don't make it visible yet!
};
notifyIcon.ContextMenu = new ContextMenu();
notifyIcon.ContextMenu.MenuItems.AddRange(new MenuItem[] { new MenuItem("Host Service") { Index = 0 }, new MenuItem("Backup Configurations", new EventHandler(delegate { bckConf.Show(); })) { Index = 1 }, new MenuItem("Network Info", new EventHandler(delegate { new form_NetworkInfo().Show(); })) { Index = 2 }, new MenuItem("About", new EventHandler(delegate { new form_AboutUs().Show(); })) { Index = 3 }, new MenuItem("Exit", new EventHandler(delegate { TerminateProgram(ProgramTerminateReason.UserRequest); })) { Index = 4 } }); 

为了更改 NotifyIconContextMenu,创建了一个名为 ChangeNotifyIconState 的 public 方法,因为需要根据生成的结果更改菜单项由程序中其他 classes 的对象声明如下:(请忽略 "CurrentServiceState" 数据类型的变量,并注意 NotifyIcon 对象被声明为 class变量)

static public void ChangeNotifyIconState(CurrentServiceState state)
{
   notifyIcon.ContextMenu.MenuItems[0].MenuItems.Clear(); // First clear all menu items of the to-be-updated block
   if (state==CurrentServiceState.Running)
   { // Service has started running; disable the start button and activate the stop and restart buttons
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = false });
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = true });
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = true });
   } else if (state==CurrentServiceState.Stopped)
   { // Service has stopped running; disable the stop and restart button and activate the start button
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Start service", new EventHandler(delegate { HostServices.Start(); })) { Index = 0, Enabled = true });
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Stop service", new EventHandler(delegate { HostServices.Stop(); })) { Index = 0, Enabled = false });
      notifyIcon.ContextMenu.MenuItems[0].MenuItems.Add(new MenuItem("Restart service", new EventHandler(delegate { HostServices.Restart(); })) { Index = 0, Enabled = false })};
   }
}

问题是:当我调用 ChangeNotifyIconState(CurrentServiceState.Running) 时,ContextMenu 所需的 MenuItems 不是 changed/updated。有人可以帮助我摆脱这种意外行为并向我解释其背后的原因吗?

提前致谢。

编辑:

我什至将 NotifyIcon 对象标记为可变对象,因为我推测这是因为编译器缓存。结果证明这不是因为制作对象 volatile 没有解决手头的问题。

下面是如何创建没有表单但带有 NotifyIcon 的应用程序的示例,以及如何更改 NotifyIconmenuContextItems 例如点击事件:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp5
{
    static class Program
    {

        private static Random rd = new Random();
        private static NotifyIcon notifyIcon;
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            NotifyIcon ni = new NotifyIcon(new System.ComponentModel.Container());
            ContextMenu cm = new ContextMenu();

            cm.MenuItems.Add(new MenuItem("First", Click));
            cm.MenuItems.Add(new MenuItem("Second", Click));
            cm.MenuItems.Add(new MenuItem("Third", Click));
            cm.MenuItems.Add(new MenuItem("Exit", (obj,e)=> { Application.Exit(); }));
            ni.Icon = new Icon(@"c:\Users\Admin\Desktop\img.ico");
            ni.Text = "Form1 (NotifyIcon example)";
            ni.ContextMenu = cm;
            ni.Visible = true;
            notifyIcon = ni;
            Application.Run();

        }

        public static bool  SomeCondition()
        {
            return (rd.Next(0, 9999) % 2) == 1;
        }

        public static void Click(object sender, EventArgs e)
        {
            if (SomeCondition())
            {
                ContextMenu cm = new ContextMenu();
                cm.MenuItems.Add(new MenuItem("Fourth", Click));
                cm.MenuItems.Add(new MenuItem("Fifth", Click));
                cm.MenuItems.Add(new MenuItem("Sixth", Click));
                cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
                notifyIcon.ContextMenu = cm;
            }
            else
            {
                ContextMenu cm = new ContextMenu();
                cm.MenuItems.Add(new MenuItem("Third", Click));
                cm.MenuItems.Add(new MenuItem("Sixth", Click));
                cm.MenuItems.Add(new MenuItem("Fourth", Click));
                cm.MenuItems.Add(new MenuItem("Exit", (obj, args) => { Application.Exit(); }));
                notifyIcon.ContextMenu = cm;
            }
        }
    }
}

下面是屏幕截图:

在应用程序启动时,将出现 notifyIcon,菜单如下所示:

因为我的条件是在 click 之后返回随机 truefalse 任何 menuItem 除了 "Exit" 将工作 Click event handler 和改变menucontext。结果,您将获得如下菜单之一: