2009-02-13 6 views
8

Ich habe versucht, meine WPF-Anwendung dazu zu bringen, Benutzer dazu aufzufordern, ihre nicht gespeicherten Änderungen entweder zu verwerfen oder abzubrechen, wenn sie mit einem TreeView navigieren.WPF: unterbricht MessageBox PreviewMouseDown?

Ich glaube, ich habe einen Fehler gefunden haben. Die MessageBox spielt nicht gut mit PreviewMouseDown. Es scheint einen Klick zu "behandeln", unabhängig davon, wie e.Handled gesetzt ist, wenn eine MessageBox angezeigt wird. anders

Für diese XAML ...

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

... vergleichen diese alternativen Methoden ...

 
Sub TreeViewNodes_PreviewMouseDown(...) 
    e.Handled = False 
End Sub 

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

verhalten sich diese beiden Methoden. Ohne die MessageBox wird TreeViewNodes_Selected() oder TreeViewThings_Expanded() ausgeführt. Mit der MessageBox werden sie nicht.

Ist das ein Fehler oder gibt es hier etwas, das ich verstehen sollte?

Antwort

2

Ich habe genau das gleiche Problem, und Sie haben recht, wenn Sie denken, dass MessageBox Dinge vermasselt. Um ehrlich zu sein, hatte ich andere Probleme mit MessageBox während der Arbeit mit Windows Forms, bevor ich zu WPF wechselte. Vielleicht ist es nur ein hundertjähriger Fehler, der ein Feature wurde (wie es oft bei Microsoft ist)?

In jedem Fall ist die einzige Lösung, die ich Ihnen anbieten kann, diejenige, die für mich gearbeitet hat. Ich hatte Probleme, eine ähnliche Situation zu bekommen, um mit einer ListBox zu arbeiten - wenn es Änderungen an den Daten im Formular gab, wenn sich die Auswahl der ListBox änderte (entweder durch Klicken auf ein neues Element oder mit den Tasten "Up" oder "Down"), Ich bot dem Benutzer eine Auswahl in der MessageBox an, ob er speichern, verwerfen oder abbrechen wollte.

Natürlich die Verwendung der direkten Ansatz der Behandlung von ListBox MouseDown oder PreviewMouseDown Ereignisse funktionierte nicht gut mit einer MessageBox. Hier ist, was funktioniert hat.

Ich habe eine Datenvorlage Artikel in meiner List-Box angezeigt werden (ich Dich fast erwartet, das gleiche haben):

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

Hinweis, wie ich habe die KeyDown und MouseDown- Event-Handler die bewegte TextBlock-Steuerelement stattdessen. Ich hielt die gleichen Code-behind:

// 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(); 
} 

Als Randbemerkung, es ist seltsam, wie Binding immer meine DataRows markiert als Modified, wenn das ausgewählte Element in der List-Box, die Itemssource auf eine Datatable gebunden hat, Änderungen (I don nicht wissen, wenn Sie DataTables/Sets verwenden). Um das zu kämpfen, verwerfen wir alle unbehandelten Änderungen, sobald die Auswahl bereits geändert wurde (weil ich alles behandeln, die im Fall MouseDown- notwendig sind, die den Stand der auftritt):

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

und die Code-behind für den Handler:

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

Das ist, was ich habe. Es funktioniert, ist aber weniger wünschenswert ...

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 

Dies erfordert den Benutzer auf „OK“ klicken, manuell einen „Discard Changes“ klicken (in der Nähe der Schaltfläche „Speichern“), klicken Sie über eine andere „Sind Sie sicher?“ Meldungsfeld und navigieren Sie dann erst wieder mit dem Baum.