C# - ToolStripMenuItem-List изменяет количество при добавлении своих элементов в другое контекстное меню - PullRequest
1 голос
/ 02 августа 2020

В настоящее время я столкнулся с этой проблемой: мой проект связывается через интерфейс TR.064 с Fritz! Box (маршрутизатором), чтобы получить информацию о пользователе в моей локальной сети.

Это действие выполняется навсегда в фоновом режиме с использованием BackgroundWorker.

BW вызывает объект класса Communication для получения списка активных хостов. Второй список содержит всех пользователей, которые находятся в определенном списке наблюдения. Пользователи в этом списке наблюдения выделяются.

Затем для каждого пользователя создается ToolStripMenuItem, отображающий имя хоста и его IP-адрес.

Все элементы добавляются во временную переменную класса stati c , чтобы передать его методу bw-RunCompleted.

Теперь этот метод очищает ContextMenuStrip из NotifyIcon и добавляет «стартовое меню», в котором есть стандартные кнопки, такие как выход, настройки, справка и т. д. c.

После этого все элементы временной переменной класса добавляются в ContextMenuStrip.

Но при этом список ToolStripItems временного контекстного меню удаляется после назначения их элементу 'main'-ContextMenuStrip, вызывающий исключение.

Например:

bw получает список из 8 хостов от маршрутизатора. Затем он правильно сохраняет их во временном меню. Во временном меню теперь 8 пунктов.

Когда я l oop через временное меню назначил каждый элемент «главному» меню, этот элемент удаляется из временного списка:

temp  |    main   |   items copied
8     |    0      |   0
7     |    1      |   1

-> выдает исключение, потому что список изменился (см. Рисунок)

private static void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    watchBoxCommunicator.askFritzBoxForHosts();

    // wait until Communicator finished running
    while (watchBoxCommunicator._isRunning) ;

    // now create a new menu if needed
    // --> only create new menu, if there are new hosts or hosts that went offline
    if (watchBoxCommunicator.hosts_on.Count > 0 || watchBoxCommunicator.hosts_off.Count > 0)
    {
        var tempMenu = new ContextMenuStrip();
        //tempMenu.Dock = DockStyle.Bottom;

        // first sort the elements in the onlineList
        // only sort the watchlist hosts, when there are objects in the list
        // the online user list must at least contain one user as the computer running this code is online
        List<GetGenericHostEntryResponse> tempListNonWatchlist = watchBoxCommunicator.onlineHosts.OrderBy(hostObject => hostObject.NewHostName).ToList();
        List<GetGenericHostEntryResponse> tempListWatchlist = new List<GetGenericHostEntryResponse>();
        try
        {
            tempListWatchlist = watchBoxCommunicator.hostsOnWatchlist.OrderBy(hostObject => hostObject.NewHostName).ToList();
        }
        catch (ArgumentNullException)
        {
            // do nothing
            tempListWatchlist = new List<GetGenericHostEntryResponse>();
        }
        finally
        {
            // back-associate the hosts to the watchBoxCommunicator object to grant access to the sorted lists by other methods
            watchBoxCommunicator.onlineHosts = tempListNonWatchlist;
            watchBoxCommunicator.hostsOnWatchlist = tempListWatchlist;
        }

        // add only the hosts that are not on the watchlist
        foreach (var host in watchBoxCommunicator.onlineHosts)
        {
            if (watchBoxCommunicator.hostsOnWatchlist.Contains(host)) continue;
            var menuItem = new ToolStripMenuItem();
            menuItem.Text = host.NewHostName + " (" + host.NewIPAddress + ")";
            menuItem.Enabled = false;
            if (host.NewInterfaceType.Equals("Ethernet"))
                menuItem.Image = Properties.Resources.network_cable_64px;
            else menuItem.Image = Properties.Resources.wi_fi_logo_64px;
            tempMenu.Items.Add(menuItem);
        }
        // add all hosts that are on the watchlist to display them at the top of the menu
        foreach (var host in watchBoxCommunicator.hostsOnWatchlist)
        {
            var menuItem = new ToolStripMenuItem();
            menuItem.Text = host.NewHostName + " (" + host.NewIPAddress + ")";
            if (host.NewInterfaceType.Equals("Ethernet"))
                menuItem.Image = Properties.Resources.network_cable_64px;
            else menuItem.Image = Properties.Resources.wi_fi_logo_64px;
            menuItem.BackColor = Color.FromArgb(255, 255, 0);
            tempMenu.Items.Add(menuItem);
        }

        // pass the menu to the RunCompleted to update the NotifyIcon's contextmenu
        argumentMenu = tempMenu;
    }
    else
    {
        argumentMenu = new ContextMenuStrip();
    }
}

private static void bw_RunCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    // if the argument's type is a contextmenustrip, update the contextmenu
    // otherwise, jump to last line and restart backgroundworker
    if (argumentMenu.Items.Count > 0)
    {
        // interrupt layout updater
        wb_menu.SuspendLayout();
        wb_menu.Items.Clear();
        wb_menu.Items.AddRange(starterMenu.Items);


        // add <argumentMenu> item-list to the item-list of <wb_menu>
        //wb_menu.Items.AddRange(argumentMenu.Items);
        ToolStripItemCollection itemC = argumentMenu.Items;
        foreach (var item in itemC)
        {
            var itemN = item as ToolStripMenuItem;
            wb_menu.Items.Add(itemN);
        }

        // update the <wb_Icon> icon
        if (watchBoxCommunicator.hostsOnWatchlist.Count == 0)
        {
            wb_Icon.Icon = Properties.Resources.WatchBoxFullGreen;
        }
        else
        {
            wb_Icon.Icon = Properties.Resources.WatchBoxFullRed;
        }

        // continue layout updater
        wb_menu.ResumeLayout();
    }

    // start the background-worker again
    bw.RunWorkerAsync();
}

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

...