Ich habe ein TextBox
und ein Button
aus meiner Sicht.
Jetzt überprüfe ich eine Bedingung beim Klicken auf die Schaltfläche. Wenn sich herausstellt, dass die Bedingung falsch ist, zeige ich dem Benutzer die Meldung an und setze den Cursor auf das TextBox
Steuerelement.
if (companyref == null)
{
var cs = new Lipper.Nelson.AdminClient.Main.Views.ContactPanels.CompanyAssociation();
MessageBox.Show("Company does not exist.", "Error", MessageBoxButton.OK,
MessageBoxImage.Exclamation);
cs.txtCompanyID.Focusable = true;
System.Windows.Input.Keyboard.Focus(cs.txtCompanyID);
}
Der obige Code befindet sich im ViewModel.
Das CompanyAssociation
ist der Ansichtsname.
Der Cursor wird jedoch nicht in der gesetzt TextBox
.
Das xaml ist:
<igEditors:XamTextEditor Name="txtCompanyID"
KeyDown="xamTextEditorAllowOnlyNumeric_KeyDown"
ValueChanged="txtCompanyID_ValueChanged"
Text="{Binding Company.CompanyId,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Width="{Binding ActualWidth, ElementName=border}"
Grid.Column="1" Grid.Row="0"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
Margin="0,5,0,0"
IsEnabled="{Binding Path=IsEditable}"/>
<Button Template="{StaticResource buttonTemp1}"
Command="{Binding ContactCommand}"
CommandParameter="searchCompany"
Content="Search"
Width="80"
Grid.Row="0" Grid.Column="2"
VerticalAlignment="Top"
Margin="0"
HorizontalAlignment="Left"
IsEnabled="{Binding Path=IsEditable}"/>
Antworten:
Lassen Sie mich Ihre Frage in drei Teilen beantworten.
Ich frage mich, was in Ihrem Beispiel "cs.txtCompanyID" ist. Ist es ein TextBox-Steuerelement? Wenn ja, dann sind Sie auf dem falschen Weg. Im Allgemeinen ist es keine gute Idee, in Ihrem ViewModel einen Verweis auf die Benutzeroberfläche zu haben. Sie können fragen "Warum?" Aber dies ist eine andere Frage, die Sie auf Stackoverflow stellen sollten :).
Der beste Weg, um Probleme mit Focus aufzuspüren, ist ... das Debuggen von .Net-Quellcode. Im Ernst. Es hat mir viele Male viel Zeit gespart. Informationen zum Aktivieren des Debuggens von .net-Quellcode finden Sie in Shawn Brukes Blog.
Der allgemeine Ansatz, mit dem ich den Fokus in ViewModel festlege, sind die angehängten Eigenschaften. Ich habe eine sehr einfache angehängte Eigenschaft geschrieben, die für jedes UIElement festgelegt werden kann. Und es kann zum Beispiel an die ViewModel-Eigenschaft "IsFocused" gebunden werden. Hier ist es:
Jetzt können Sie in Ihrer Ansicht (in XAML) diese Eigenschaft an Ihr ViewModel binden:
Hoffe das hilft :). Wenn es sich nicht auf die Antwort Nr. 2 bezieht.
Prost.
quelle
Keyboard.Focus(uie);
von IhrerOnIsFocusedPropertyChanged
Veranstaltung aus anrufen , wenn Sie möchten, dass Ihre Steuerung sowohl den Tastaturfokus als auch den logischen Fokus erhält...if ((bool)e.NewValue && uie.Dispatcher != null) { uie.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => uie.Focus())); // invoke behaves nicer, if e.g. you have some additional handler attached to 'GotFocus' of UIE. uie.SetValue(IsFocusedProperty, false); // reset bound value if possible, to allow setting again ...
Manchmal muss ich sogar 'IsFocused' im ViewModel auf false zurücksetzen, wenn ich den Fokus mehrmals setzen möchte. Aber dann funktioniert es, wo einige andere Methoden fehlgeschlagen sind.Ich weiß, dass diese Frage inzwischen tausendmal beantwortet wurde, aber ich habe einige Änderungen an Anvakas Beitrag vorgenommen, von denen ich denke, dass sie anderen helfen werden, die ähnliche Probleme hatten wie ich.
Erstens habe ich die oben angehängte Eigenschaft wie folgt geändert:
Mein Grund für das Hinzufügen der Sichtbarkeitsreferenzen waren Registerkarten. Wenn Sie die angehängte Eigenschaft auf einer anderen Registerkarte außerhalb der ursprünglich sichtbaren Registerkarte verwendet haben, hat die angehängte Eigenschaft anscheinend erst funktioniert, nachdem Sie das Steuerelement manuell fokussiert haben.
Das andere Hindernis bestand darin, eine elegantere Methode zum Zurücksetzen der zugrunde liegenden Eigenschaft auf false zu schaffen, wenn sie den Fokus verlor. Hier kamen die Ereignisse mit verlorenem Fokus ins Spiel.
Wenn es eine bessere Möglichkeit gibt, das Sichtbarkeitsproblem zu lösen, lassen Sie es mich bitte wissen.
Hinweis: Vielen Dank an Apfelkuacha für den Vorschlag, BindsTwoWayByDefault in die DependencyProperty aufzunehmen. Ich hatte das vor langer Zeit in meinem eigenen Code getan, aber diesen Beitrag nie aktualisiert. Der Modus = Zwei Wege ist aufgrund dieser Änderung im WPF-Code nicht mehr erforderlich.
quelle
fe.Dispatcher.BeginInvoke(new Action(() => { fe.Focus(); }), DispatcherPriority.Loaded);
dass es aktualisiert wird, nachdem es geladen wurde. Weitere Informationen hier: telerik.com/forums/isfocused-property#OXgFYZFOg0WZ2rxidln61QIch denke, der beste Weg ist, das MVVM-Prinzip sauber zu halten. Sie müssen also im Grunde die Messenger-Klasse verwenden, die mit dem MVVM Light geliefert wird, und hier ist, wie Sie es verwenden:
Schreiben Sie in Ihrem Ansichtsmodell (exampleViewModel.cs) Folgendes
Schreiben Sie jetzt in Ihre View.cs (nicht in die XAML die view.xaml.cs) Folgendes in den Konstruktor
Diese Methode funktioniert einwandfrei und mit weniger Code und unter Beibehaltung der MVVM-Standards
quelle
Keines davon hat genau für mich funktioniert, aber zum Nutzen anderer habe ich es letztendlich auf der Grundlage einiger der hier bereits bereitgestellten Codes geschrieben.
Die Verwendung wäre wie folgt:
Und die Implementierung wäre wie folgt:
quelle
Dies ist ein alter Thread, aber es scheint keine Antwort mit Code zu geben, die die Probleme mit Anavankas akzeptierter Antwort behebt: Es funktioniert nicht, wenn Sie die Eigenschaft im Ansichtsmodell auf false setzen oder wenn Sie Ihre Eigenschaft auf setzen true, der Benutzer klickt manuell auf etwas anderes und setzt es dann erneut auf true. Auch in diesen Fällen konnte ich Zamotics Lösung nicht zuverlässig zum Laufen bringen.
Wenn ich einige der obigen Diskussionen zusammenfasse, erhalte ich den folgenden Code, der diese Probleme behandelt, denke ich:
Trotzdem ist dies für etwas, das in Codebehind in einer Zeile ausgeführt werden kann, immer noch komplex, und CoerceValue ist nicht wirklich dazu gedacht, auf diese Weise verwendet zu werden. Vielleicht ist Codebehind der richtige Weg.
quelle
In meinem Fall funktionierte die FocusExtension erst, als ich die Methode OnIsFocusedPropertyChanged änderte. Das Original arbeitete nur beim Debuggen, als ein Haltepunkt den Prozess stoppte. Zur Laufzeit ist der Prozess zu schnell und nichts ist passiert. Mit dieser kleinen Modifikation und der Hilfe unseres Freundes Task funktioniert dies in beiden Szenarien einwandfrei.
quelle
Das Problem ist, dass wenn IsUserNameFocused einmal auf true gesetzt ist, es niemals false sein wird. Dies löst es, indem GotFocus und LostFocus für das FrameworkElement behandelt werden.
Ich hatte Probleme mit der Formatierung des Quellcodes. Hier ist ein Link
quelle
Anvakas brillanter Code ist für Windows Desktop-Anwendungen. Wenn Sie wie ich sind und dieselbe Lösung für Windows Store-Apps benötigen, ist dieser Code möglicherweise hilfreich:
quelle
Für diejenigen, die versuchten, die oben genannte Lösung von Anvaka zu verwenden, gab es Probleme mit der Bindung, die nur beim ersten Mal funktionierte, da lostfocus die Eigenschaft nicht auf false aktualisieren würde. Sie können die Eigenschaft jedes Mal manuell auf false und dann auf true setzen. Eine bessere Lösung könnte jedoch darin bestehen, in Ihrer Eigenschaft Folgendes zu tun:
Auf diese Weise müssen Sie es immer nur auf true setzen, und es wird fokussiert.
quelle
Ich verwende WPF / Caliburn Micro und habe festgestellt, dass "dfaivre" hier eine allgemeine und praktikable Lösung gefunden hat: http://caliburnmicro.codeplex.com/discussions/222892
quelle
Ich habe eine Lösung gefunden, indem ich den Code wie folgt bearbeitet habe. Es ist nicht erforderlich, die Bindungseigenschaft zuerst auf False und dann auf True festzulegen.
quelle
Für Silverlight:
LoginViewModel.cs:
Login.xaml:
ODER
Um den Fokus zu setzen, sollte dies nur im Code erfolgen:
Denken Sie daran, dass dieses Plugin Teil einer HTML-Seite ist, sodass andere Steuerelemente auf der Seite möglicherweise den Fokus haben
quelle
Sie können das ViewCommand- Entwurfsmuster verwenden. Es beschreibt eine Methode für das MVVM-Entwurfsmuster zum Steuern einer Ansicht aus einem ViewModel mit Befehlen.
Ich habe es basierend auf dem Vorschlag von King A.Majid implementiert, die MVVM Light Messenger-Klasse zu verwenden. Die ViewCommandManager-Klasse behandelt das Aufrufen von Befehlen in verbundenen Ansichten. Dies ist im Grunde die andere Richtung der regulären Befehle, in diesen Fällen, in denen ein ViewModel in seiner Ansicht eine Aktion ausführen muss. Es verwendet Reflexionen wie datengebundene Befehle und WeakReferences, um Speicherverluste zu vermeiden.
http://dev.unclassified.de/source/viewcommand (auch auf CodeProject veröffentlicht)
quelle
Niemand scheint den letzten Schritt aufgenommen zu haben, um das Aktualisieren von Attributen über gebundene Variablen zu vereinfachen. Folgendes habe ich mir ausgedacht. Lassen Sie mich wissen, ob es einen besseren Weg gibt, dies zu tun.
XAML
ViewModel
quelle
Zunächst möchte ich Avanka dafür danken, dass sie mir bei der Lösung meines Fokusproblems geholfen hat. Es gibt jedoch einen Fehler in dem Code, den er gepostet hat, nämlich in der Zeile: if (e.OldValue == null)
Das Problem, das ich hatte, war, dass e.oldValue nicht mehr null ist, wenn Sie zum ersten Mal in Ihre Ansicht klicken und das Steuerelement fokussieren. Wenn Sie dann die Variable so einstellen, dass das Steuerelement zum ersten Mal fokussiert wird, werden die Handler für den verlorenen Fokus und den gotfocus nicht festgelegt. Meine Lösung dafür war wie folgt:
quelle
Mach das einfach:
quelle
Nachdem ich die akzeptierte Antwort implementiert hatte, stieß ich auf ein Problem, dass die TextBox beim Navigieren in Ansichten mit Prism immer noch nicht fokussiert wurde. Eine geringfügige Änderung am PropertyChanged-Handler hat das Problem behoben
quelle
Ein alternativer Ansatz basierend auf der Antwort von @Sheridan hier
Richten Sie in Ihrem Ansichtsmodell Ihre Bindung wie gewohnt ein und setzen Sie dann SomeTextIsFocused auf true, um den Fokus auf Ihr Textfeld festzulegen
quelle
Ich habe Crucial gefunden ‚s Lösung für das Problem IsVisible sehr nützlich. Es hat mein Problem nicht vollständig gelöst, aber ein zusätzlicher Code, der dem gleichen Muster für das IsEnabled-Muster folgt, hat es getan.
Zur IsFocusedChanged-Methode habe ich hinzugefügt:
Und hier ist der Handler:
quelle
quelle
quelle