'How to use a WPF ContextMenu with NotifyIcon

I want to open a WPF ContextMenu when the user clicks the system tray icon. With Windows Forms this is straight-forward, just call notifyIcon.ContextMenu = contextMenu and you're set.

On WPF we can not set the ContextMenu that easily because WPF's ContextMenu class is not related to Forms ContextMenu. The alternative I have been pursuing is to handle NotifyIcon's Click event to open the WPF-style ContextMenu.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // This is intended to be a system tray application so we hide the window
        this.Visibility = Visibility.Hidden;

        // Winform context menu
        // The context menu closes when the user clicks anywhere outside the menu
        // The user can navigate the menu with the keyboard arrows and close with ESC
        var notifyIcon1 = new System.Windows.Forms.NotifyIcon();
        var contextMenu = new System.Windows.Forms.ContextMenu();
        var menuItem = new System.Windows.Forms.MenuItem();
        menuItem.Text = "WinForm Menu Item";
        contextMenu.MenuItems.Add(menuItem);
        notifyIcon1.ContextMenu = contextMenu;
        notifyIcon1.Icon = Properties.Resources.ico;
        notifyIcon1.Visible = true;

        // WPF context menu
        // The user cannot close the menu by clicking outside its bounds
        // Does not detect any keyboard input
        var notifyIcon2 = new System.Windows.Forms.NotifyIcon();
        notifyIcon2.Icon = Properties.Resources.ico;
        notifyIcon2.Visible = true;
        notifyIcon2.Click += NotifyIcon2_Click;
    }

    private void NotifyIcon2_Click(object sender, EventArgs e)
    {
        var contextMenu = new ContextMenu();
        var menuItem = new MenuItem();
        menuItem.Header = "WPF Menu Item";
        contextMenu.Items.Add(menuItem);
        contextMenu.IsOpen = true;
    }
}

The issue with this approach is that the WPF ContextMenu never gets any hint that the user has navigated away from the menu and should close (Eg, when the user clicks outside the bounds of the menu). None of the Focus or MouseCapture events are ever triggered and I am unable to close the menu other than by clicking on one of its items.

So the question here, to put slightly different, is: how do I properly emulate the NotifyIcon's ContextMenu closing behavior using WPF's ContextMenu?



Solution 1:[1]

I faced similar issue. You can try if you want

notifyIcon1.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon1.ContextMenuStrip.Items.Add("YourMenuItem",null, MenuItemEvent);

I hope this will solve the problem.

Solution 2:[2]

I managed to find a workaround that works for me, it doesn't quite do EXACTLY what I originally intended but works well enough. For anyone that might be looking to do something similar here is what I ended up doing.

Instead of importing it into the actual Django Auth User password field, add a new old_password field to your users and import the old hashed passwords into there.

Then edit your authenticate function (likely in backends.py) to check the old_password field with bcrypt if the password check fails on login:

            if user.check_password(password):
                return user
            else: #didnt match check if its an old user
                if user.old_password != "":
                    if bcrypt.checkpw(bytes(password, 'utf-8'), bytes(user.old_password, 'utf-8')):
                        user.set_password(password)
                        user.save()
                        return user

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tasos K.
Solution 2 user2300846