-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Description
RibbonMenuItem.UpdateDropDownPosition
is launched asynchronously (BeginInvoke) from RibbonMenuItem.OnIsSubmenuOpenChanged
. Suppose an event handler plugged on SubmenuOpened
closes the sub menu. Then the effective call to UpdateDropDownPosition will happen after the menu has been closed. In that case, an InvalidOperationException will be thrown by Visual.PointToScreen
called from UpdateDropDownPosition because it makes no sense on a window that is off screen.
I'm aware this looks like an obscure corner case, but I stumbled upon it quite naturally while making a dynamic submenu whose items are regenerated at every opening: if the generated list is empty, I just close the menu. I can work around this by closing the menu asynchronously, except I get a flickering.
Would it be possible to add a check at the start of UpdateDropDownPosition
to do nothing if IsSubmenuOpen
is false?
Reproduction Steps
public void RibbonSubMenuCrash()
{
var d = new RibbonMenuButton() { Label = "DD" }; // drop down button in ribbon
var it = new RibbonMenuItem() { Header = "item with submenu" }; // menu item with a sub item inside d
d.Items.Add(it);
it.Items.Add(new RibbonMenuItem());
// event handler to close it's submenu; sounds pointless but in my real use case it is only closing in some specific circumstances
it.SubmenuOpened += (o, e) =>
{
d.IsDropDownOpen = false; // causes a crash in the last doevents
};
var w = new RibbonWindow();
var r = new System.Windows.Controls.Ribbon.Ribbon();
w.Content = r;
var t = new RibbonTab();
r.Items.Add(t);
var g = new RibbonGroup();
t.Items.Add(g);
g.Items.Add(d);
w.Show();
// simulates opening d, then attempting to open the sub menu
Action doevents = () => Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
doevents();
d.IsDropDownOpen = true;
doevents();
it.IsSubmenuOpen = true;
doevents(); // invalidoperationexception thrown from async call to RibbonMenuItem.UpdateDropDownPosition
}
Expected behavior
sub menu not appearing
Actual behavior
Exception is thrown.
Regression?
No response
Known Workarounds
Closing the submenu asynchronously:
Dispatcher.CurrentDispatcher.BeginInvoke(() => d.IsDropDownOpen = false);
Impact
Can't have a dynamic sub menu without flickering.
Configuration
.Net 8
window 10 x64
Most likely not system specific as the reason for the crash is quite clear from the code.
Other information
No response