2008-10-21 7 views
12

J'ai une fenêtre WPF pour éditer les informations de la base de données, qui est représentée à l'aide d'un objet Entity Framework. Lorsque l'utilisateur ferme la fenêtre, je voudrais remarquer dans l'événement Closing si les informations ont changé et afficher une boîte de message proposant d'enregistrer les changements dans la base de données.WPF: Les modifications de la zone de texte avec focus ne sont validées qu'après l'ouverture de l'événement de fermeture

Malheureusement, les modifications apportées à l'édition actuellement ciblée ne sont pas affectées à la source de liaison tant que l'édition n'a pas été mise au point, ce qui se produit à un certain moment après le traitement de l'événement de fermeture.

Idéalement, il y aurait une routine qui valide tous les changements dans la hiérarchie de vue que je pourrais appeler avant de vérifier si mon entité a été modifiée. J'ai également recherché des informations sur la suppression par programme du focus dans le contrôle avec focus, mais je n'arrive pas à comprendre comment le faire.

Ma question est, comment est-ce généralement géré?

+0

double question: http://stackoverflow.com/questions/57493/ wpf-databind-before-saving # 229738 – Sam

+0

Une autre façon de résoudre ceci: http://stackoverflow.com/a/17458095/194717 – Tony

Répondre

7

Cela devrait vous être assez près:



private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    ForceDataValidation(); 
} 


private static void ForceDataValidation() 
{ 
    TextBox textBox = Keyboard.FocusedElement as TextBox; 

    if (textBox != null) 
    { 
     BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty); 
     if (be != null && !textBox.IsReadOnly && textBox.IsEnabled) 
     { 
      be.UpdateSource(); 
     } 
    } 

} 


+1

J'ai également vérifié pour voir si la zone de texte avait édités: 'if ((textBox! = null) && (textBox.CanUndo)) {...} ' – jhr

0

La façon la plus simple est de mettre quelque part au centre. Vous pouvez régler le focus immédiatement, mais le réglage de la mise au point partout déclenchera l'LostFocus-événement sur tout type de contrôle et de faire mettre à jour ses trucs:

IInputElement x = System.Windows.Input.Keyboard.FocusedElement; 
DummyField.Focus(); 
x.Focus(); 

Une autre façon serait d'obtenir l'élément ciblé, obtenir l'élément de liaison de l'élément ciblé et déclenche la mise à jour manuellement. Un exemple pour TextBox et ComboBox (vous auriez besoin d'ajouter tout type de contrôle que vous devez prendre en charge):

TextBox t = Keyboard.FocusedElement as TextBox; 
if ((t != null) && (t.GetBindingExpression(TextBox.TextProperty) != null)) 
    t.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
ComboBox c = Keyboard.FocusedElement as ComboBox; 
if ((c != null) && (c.GetBindingExpression(ComboBox.TextProperty) != null)) 
    c.GetBindingExpression(ComboBox.TextProperty).UpdateSource(); 
1

En supposant qu'il y ait plus d'un contrôle dans la séquence de tabulation, la solution suivante semble être complète et générale (couper-coller juste) ...

Control currentControl = System.Windows.Input.Keyboard.FocusedElement as Control; 

if (currentControl != null) 
{ 
    // Force focus away from the current control to update its binding source. 
    currentControl.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); 
    currentControl.Focus(); 
} 
21

En WPF vous pouvez changer Binding de mettre à jour la source sur la modification, plutôt que de perdre le focus. Cela se fait en définissant la propriété UpdateSourceTrigger-PropertyChanged:

Value="{Binding Path=MyProperty, UpdateSourceTrigger=PropertyChanged}" 
+0

Meilleure réponse, car elle est pure MVVM, et n'implique pas de déconner avec les événements. Néanmoins insatisfaisant, que ce n'est pas le déclencheur par défaut, car il semble que le comportement de liaison bidirectionnelle le plus intuitif pour moi ... – M463

3

Peut-être que vous devez enlever le focus de l'élément courant

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    FocusManager.SetFocusedElement(this, null); 
} 
Questions connexes