Ho fatto un po 'di casino con PreviewLostKeyboardFocus
che quasi ti porta lì. Ho visto un paio di implementazioni usando LostFocus
, ma questo semplicemente costringe a concentrarsi sullo TextBox
dopo che ha perso la messa a fuoco e si può facilmente vedere questo spostamento sullo schermo. Fondamentalmente, sto solo cercando lo stesso tipo di comportamento che si può ottenere usando OnValidating
in WinForms.Qual è il modo migliore per evitare di perdere l'attenzione su TextBox quando si verifica un errore di convalida?
risposta
A mio parere, il modo migliore è generalmente non farlo. È quasi sempre meglio disabilitare semplicemente gli altri controlli o impedire il salvataggio fino a quando il valore non è valido.
Ma se il vostro design davvero bisogno di questa capacità, qui è quello che si dovrebbe fare:
Intercept versione
Preview
degli eventi di tastiera e mouse al vostro livello di finestra, o quello che volete per impedire modifiche di messa a fuoco la portata all'interno (ad esempio, forse non la barra dei menu).Quando il Tab KeyDown o Return KeyDown viene rilevato nella casella di testo o quando un MouseDown viene rilevato all'esterno della casella di testo mentre è attivo, chiamare UpdateSource() sull'espressione di associazione, quindi se la convalida non è riuscita set Handled = true per impedire che l'evento KeyDown o MouseDown venga ulteriormente elaborato.
Continuare anche a gestire
PreviewLostKeyboardFocus
per individuare eventuali cause di modifica della messa a fuoco che non provengono da tastiera o mouse o che l'altro codice non ha riconosciuto.
come catturare gli eventi del mouse globali (a livello di finestra)? Se disponiamo di un controllo del contenitore e l'attivazione dovrebbe rimanere all'interno dell'editor fino a quando non verranno passati dati validi. –
Per aggiungere sulla risposta di Ray:
UpdateSource si chiama in questo modo:
BindingExpression be = userTextbox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
Inoltre, in alternativa è possibile impostare la casella di testo vincolante:
UpdateSourceTrigger = "PropertyChanged";
Quest'ultimo causerà un controllo continuo, mentre il primo controllerà quando necessario (performante).
Se si tenta di mettere a fuoco un elemento all'interno del proprio gestore di LostFocus, si troverà di fronte a StackOverflowException, non sono sicuro della causa principale (ho il sospetto che il tipo di focus rimbalzi), ma c'è una soluzione facile: inviarlo .
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var element = (sender as TextBox);
if (!theTextBoxWasValidated())
{
// doing this would cause a StackOverflowException
// element.Focus();
var restoreFocus = (System.Threading.ThreadStart)delegate { element.Focus(); };
Dispatcher.BeginInvoke(restoreFocus);
}
}
Attraverso Dispatcher.BeginInvoke è assicurarsi che il ripristino della messa a fuoco non ottenere nel modo della perdita in corso di messa a fuoco (e di evitare l'eccezione brutto che ci si faccia in altro modo)
Facendo attenzione in un controllo può portare a una scarsa esperienza utente ... Basta essere sicuri di lasciare che gli utenti escano facilmente da quella finestra di dialogo/finestra ... –