Tengo 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, utilizar el enfoque directo para manejar los eventos MouseDown o PreviewMouseDown de ListBox no funcionó bien con un MessageBox. Esto es lo que funcionó.
que tienen una plantilla de datos para mostrar los elementos en mi cuadro de lista (estoy casi te esperando tener la misma):
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=NAME}" KeyDown="checkForChanges" MouseDown="checkForChanges"/>
</DataTemplate>
</ListBox.ItemTemplate>
Nota cómo he moví los controladores de eventos KeyDown y MouseDown a la Control TextBlock en su lugar. Me quedé con el mismo código subyacente:
// 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, que es extraño cómo encuadernación siempre marca mi DataRows, modificadas cuando el elemento seleccionado en el cuadro de lista, que tiene ItemsSource unido a un DataTable, los cambios (I Don no sé si está usando DataTables/Sets). Para combatir esto, descarto cualquier cambio no controladas una vez que la selección ya ha sido cambiado (porque yo manejo todo lo que es necesario en el evento MouseDown que se produce antes de que):
<ListBox IsSynchronizedWithCurrentItem="True" [...] SelectionChanged="clearChanges"> ... </ListBox>
Y el código subyacente para el controlador:
private void clearChanges(object sender, SelectionChangedEventArgs e) {
Data.cancelChanges();
}