notification alertas .net wpf events messagebox

.net - alertas - openfiledialog wpf



WPF: ¿MessageBox rompe PreviewMouseDown? (2)

He intentado que mi aplicación WPF solicite a los usuarios descartar los cambios que no se han guardado o cancelar cuando navegan con TreeView.

Creo que encontré un error. El MessageBox no funciona bien con PreviewMouseDown. Parece que "maneja" un clic independientemente de cómo se configure e.Handled si se muestra un MessageBox.

Para este XAML ...

<TreeView Name="TreeViewThings" ... PreviewMouseDown="TreeViewThings_PreviewMouseDown" TreeViewItem.Expanded="TreeViewThings_Expanded" TreeViewItem.Selected="TreeViewThings_Selected" >

... compare estos métodos alternativos ...

Sub TreeViewNodes_PreviewMouseDown(...) e.Handled = False End Sub Sub TreeViewNodes_PreviewMouseDown(...) MessageBox.Show("Test", "Test", MessageBoxButton.OK) e.Handled = False End Sub

Estos dos métodos se comportan de manera diferente. Sin MessageBox, se ejecutarán TreeViewNodes_Selected() o TreeViewThings_Expanded() . Con el MessageBox, no lo harán.

¿Es esto un error o hay algo pasando aquí que debería entender?


Esto es lo que tengo. Funciona, pero es menos deseable ...

Sub TreeViewNodes_PreviewMouseDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) If UnsavedChangesExist() Then MessageBox.Show("You have unsaved changes.", "Unsaved Changes", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK) e.Handled = True End If End Sub

Esto requiere que el usuario haga clic en "Aceptar", haga clic manualmente en el botón "Descartar cambios" (cerca del botón "Guardar"), haga clic en otro "¿Está seguro?" cuadro de mensaje, y solo luego navegar con el árbol nuevamente.


Estoy teniendo exactamente el mismo problema y tienes razón al pensar que MessageBox está arruinando las cosas. Para ser sincero, he tenido otros problemas con MessageBox mientras trabajaba con Windows Forms antes de cambiar a WPF. Tal vez es solo un error centenario que se convirtió en una característica (como suele suceder con Microsoft).

En cualquier caso, la única solución que puedo ofrecerte es la que me ha funcionado. Estaba teniendo problemas para hacer que una situación similar funcione con un ListBox, si hubo cambios en los datos del formulario, cuando la selección del ListBox cambió (haciendo clic en un elemento nuevo o usando las teclas "Arriba" o "Abajo"), Ofrecí al usuario una opción en el MessageBox ya sea para guardar, descartar o cancelar.

Naturalmente, usar el enfoque directo de manejar los eventos MouseDown o PreviewMouseDown de ListBox no funcionó bien con un MessageBox. Esto es lo que funcionó.

Tengo una plantilla de datos para mostrar elementos en mi ListBox (casi espero que tengas el mismo):

<ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=NAME}" KeyDown="checkForChanges" MouseDown="checkForChanges"/> </DataTemplate> </ListBox.ItemTemplate>

Tenga en cuenta cómo he movido los controladores de eventos KeyDown y MouseDown al control TextBlock en su lugar. Guardé el mismo código detrás:

// The KeyDown handler private void checkForChanges(object sender, KeyEventArgs e) { e.Handled = checkForChanges(); } // Method that checks if there are changes to be saved or discard or cancel private bool checkForChanges() { if (Data.HasChanges()) { MessageBoxResult answer = MessageBox.Show("There are unsaved changes. Would you like to save changes now?", "WARNING", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (answer == MessageBoxResult.Yes) { Data.AcceptDataChanges(); } else if (answer == MessageBoxResult.Cancel) { return true; } return false; } return false; } // The MouseDown handler private void checkForChanges(object sender, MouseButtonEventArgs e) { e.Handled = checkForChanges(); }

Como nota al margen, es curioso cómo Binding siempre marca mis DataRows como Modificadas cuando el elemento seleccionado en el ListBox, que tiene ItemsSource vinculado a una DataTable, cambia (no sé si estás usando DataTables / Sets). Para combatir eso, descarto cualquier cambio no controlado una vez que la selección ya ha sido modificada (porque manejo todo lo que sea necesario en el evento MouseDown que ocurre antes de eso):

<ListBox IsSynchronizedWithCurrentItem="True" [...] SelectionChanged="clearChanges"> ... </ListBox>

Y el código detrás del controlador:

private void clearChanges(object sender, SelectionChangedEventArgs e) { Data.cancelChanges(); }