ContextMenu не скрывается при выполнении команды

155
21 июля 2019, 02:00

Использую библиотеку Hardcodet.Wpf.TaskbarNotification для отображения в трее иконки приложения:

<tb:TaskbarIcon x:Key="NotifyIcon"
                IconSource="/Resources/iconOn.ico"
                ToolTipText="{Binding Source={StaticResource Lang}, XPath=tt6}"
                DoubleClickCommand="{Binding DoubleMouseClick}"
                ContextMenu="{StaticResource SysTrayMenu}"
                PreviewTrayContextMenuOpen="NotifyIcon_OnPreviewTrayContextMenuOpen">
    <!-- self-assign a data context (could also be done programmatically) -->
    <tb:TaskbarIcon.DataContext>
        <mpAutoUpdater:NotifyIconViewModel/>
    </tb:TaskbarIcon.DataContext>
</tb:TaskbarIcon>

Контекстное меню лежит в ресурсах. Особо смотреть там не на что. Для контекстного меню установлено свойство StaysOpen="False". Для пункта меню установлено свойство StaysOpenOnClick="False". К пункту меню привязана команда:

public ICommand CheckUpdatesCommand
{
    get
    {
        return new DelegateCommand
        {
            CommandAction = () =>
            {
                ModuleUpdate.CheckAndUpdateModule(true);
                Updater.CheckAndUpdateAll(true);
            }
        };
    }
}

Реализация DelegateCommand взята прям из примера для библиотеки:

public class DelegateCommand : ICommand
{
    public Action CommandAction { get; set; }
    public Func<bool> CanExecuteFunc { get; set; }
    public void Execute(object parameter)
    {
        CommandAction();
    }
    public bool CanExecute(object parameter)
    {
        return CanExecuteFunc == null || CanExecuteFunc();
    }
    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

Так вот - при нажатии на пункт в меню контекстное меню продолжает отображаться открытым, пока выполняется код в команде. Я уже пробовал выносить в другой поток вот так:

public ICommand CheckUpdatesCommand
{
    get
    {
        return new DelegateCommand
        {
            CommandAction = () =>
            {
                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
                {
                    ModuleUpdate.CheckAndUpdateModule(true);
                    Updater.CheckAndUpdateAll(true);
                }));
            }
        };
    }
}

Бесполезно.

Что самое интересное - меню остается висеть не как нормальное меню, а как визуальный артефакт на экране. Т.е. оно уже не активно и по нему не кликнуть.

Я пробовал и ставить значение IsOpen="False" перед выполнением команды - тоже не помогло.

Что еще можно попробовать?

UPD: Добавляю gif'ку с отображением проблемы: при клике на пункт "Проверить обновления" работают методы, которые могут занять некоторое время (пару секунд). Они работают в основном потоке. И пока работа их не закончится - меню не исчезает. Вот это и нужно устранить

Answer 1

В общем получилось только вот так:

public ICommand CheckUpdatesCommand
{
    get
    {
        return new DelegateCommand
        {
            CommandAction = async () =>
            {
                await Task.Run(async () =>
                {
                    await Task.Delay(500);
                    void RunUpdaters()
                    {
                        ModuleUpdate.CheckAndUpdateModule(true);
                        Updater.CheckAndUpdateAll(true);
                    }
                    await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(RunUpdaters));
                });
            }
        };
    }
}

Только в таком случае меню у меня пропадает перед началом работы.

P.S. Методы ModuleUpdate.CheckAndUpdateModule(true); и Updater.CheckAndUpdateAll(true); должны работать в основном потоке, так как там происходит много обращений к главному UI

READ ALSO
Обновлять свойство Button при изменении Text у TextBox

Обновлять свойство Button при изменении Text у TextBox

В окне кнопка, у которой свойство IsEnabled должно быть true только если Text в TextBox соответствует паттерну RegexА в других случаях false

160
Получения url страницы в ajax запросе

Получения url страницы в ajax запросе

Есть ajax запросРезультатом которого если всё хорошо будет срабатывать

169
Почему в проекте можно обратится к зависимостям подключенной dll?

Почему в проекте можно обратится к зависимостям подключенной dll?

Всем привет!Сразу извиняюсь, если очень глупо задал вопрос

141
GroupBy работает не корректно в IQueryable

GroupBy работает не корректно в IQueryable

Работаю с Entity FrameworkЕсть класс

140