From 569722a5b0b968a33c2e1802b941742b4cdbe605 Mon Sep 17 00:00:00 2001 From: Peter Kirmeier Date: Sun, 17 Sep 2023 18:29:51 +0200 Subject: [PATCH] Add protection against DisconnectedItem as sender object in mouse event handlers Workaround was added in early development stage already: 1f985c53aac8076e807df67778f435201c2bb115 However, it was meant to be no longer occurring, so detection was removed here: 6ebfed5f78efa23fd0bd2c5dbad5221fa723133b 3f09f4018830fc439e32dfc801b021ad521eabe6 3153032110c928a8fddcb4010e5a52b5048b1003 Since it occurred again, we reintroduce this fix at least on all mouse events. This time, we check for the expected object type rather looking up the item in the list. --- UserInterface/Menu.xaml.cs | 61 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/UserInterface/Menu.xaml.cs b/UserInterface/Menu.xaml.cs index c29adaf..920233c 100644 --- a/UserInterface/Menu.xaml.cs +++ b/UserInterface/Menu.xaml.cs @@ -1146,14 +1146,18 @@ namespace SystemTrayMenu.UserInterface { if (!isShellContextMenuOpen) { - CellMouseEnter?.Invoke((RowData)((ListViewItem)sender).Content); + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) + { + CellMouseEnter?.Invoke(rowData); + } } } private void ListViewItem_MouseLeave(object sender, MouseEventArgs e) { - var content = ((ListViewItem)sender).Content; - if (content is RowData rowData) + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) { rowData.IsClicked = false; countLeftMouseButtonClicked = 0; @@ -1169,39 +1173,56 @@ namespace SystemTrayMenu.UserInterface } } - private void ListViewItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) => - CellMouseDown?.Invoke((RowData)((ListViewItem)sender).Content); + private void ListViewItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) + { + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) + { + CellMouseDown?.Invoke(rowData); + } + } private void ListViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { - RowData rowData = (RowData)((ListViewItem)sender).Content; - rowData.IsClicked = true; - countLeftMouseButtonClicked = e.ClickCount; + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) + { + rowData.IsClicked = true; + countLeftMouseButtonClicked = e.ClickCount; + } } private void ListViewItem_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { - RowData rowData = (RowData)((ListViewItem)sender).Content; - if (rowData.IsClicked) + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) { - // Same row has been called with PreviewMouseLeftButtonDown without leaving the item, so we can call it a "click". - // The click count is also taken from Down event as it seems not being correct in Up event. - rowData.OpenItem(countLeftMouseButtonClicked); + if (rowData.IsClicked) + { + // Same row has been called with PreviewMouseLeftButtonDown without leaving the item, so we can call it a "click". + // The click count is also taken from Down event as it seems not being correct in Up event. + rowData.OpenItem(countLeftMouseButtonClicked); + } + + rowData.IsClicked = false; } countLeftMouseButtonClicked = 0; - rowData.IsClicked = false; } private void ListViewItem_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { - // At mouse location - Point position = Mouse.GetPosition(this); - position.Offset(Left, Top); + // "DisconnectedItem" protection + if (((ListViewItem)sender).Content is RowData rowData) + { + // At mouse location + Point position = Mouse.GetPosition(this); + position.Offset(Left, Top); - isShellContextMenuOpen = true; - ((RowData)((ListViewItem)sender).Content).OpenShellContextMenu(position); - isShellContextMenuOpen = false; + isShellContextMenuOpen = true; + rowData.OpenShellContextMenu(position); + isShellContextMenuOpen = false; + } } } }