Myślę, że mam a TextBox
i Button
.
Teraz sprawdzam warunek po kliknięciu przycisku i jeśli warunek okaże się fałszywy, wyświetlam wiadomość użytkownikowi, a następnie muszę ustawić kursor na TextBox
kontrolce.
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);
}
Powyższy kod znajduje się w ViewModel.
To CompanyAssociation
jest nazwa widoku.
Ale kursor nie jest ustawiany w TextBox
.
XAML to:
<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}"/>
Odpowiedzi:
Odpowiem na twoje pytanie w trzech częściach.
Zastanawiam się, co to jest „cs.txtCompanyID” w Twoim przykładzie? Czy jest to formant TextBox? Jeśli tak, to jesteś na złej drodze. Ogólnie rzecz biorąc, nie jest dobrym pomysłem umieszczanie jakichkolwiek odniesień do interfejsu użytkownika w swoim ViewModel. Możesz zapytać „Dlaczego?” ale to jest kolejne pytanie do opublikowania w Stackoverflow :).
Najlepszym sposobem śledzenia problemów z Focus jest ... debugowanie kodu źródłowego .Net. Bez żartów. Zaoszczędziło mi to wiele czasu. Aby włączyć debugowanie kodu źródłowego .net, zapoznaj się z blogiem Shawn Bruke .
Wreszcie, ogólne podejście, którego używam do ustawiania fokusu z ViewModel, to Attached Properties. Napisałem bardzo prostą załączoną właściwość, którą można ustawić na dowolnym elemencie UIElement. I może być na przykład powiązany z właściwością ViewModel „IsFocused”. Oto ona:
public static class FocusExtension { public static bool GetIsFocused(DependencyObject obj) { return (bool) obj.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject obj, bool value) { obj.SetValue(IsFocusedProperty, value); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached( "IsFocused", typeof (bool), typeof (FocusExtension), new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); private static void OnIsFocusedPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var uie = (UIElement) d; if ((bool) e.NewValue) { uie.Focus(); // Don't care about false values. } } }
Teraz w Twoim widoku (w języku XAML) możesz powiązać tę właściwość z Twoim ViewModel:
<TextBox local:FocusExtension.IsFocused="{Binding IsUserNameFocused}" />
Mam nadzieję że to pomoże :). Jeśli nie odnosi się do odpowiedzi nr 2.
Twoje zdrowie.
źródło
Keyboard.Focus(uie);
zOnIsFocusedPropertyChanged
wydarzenia, jeśli chcesz, aby twoja kontrola otrzymała Focus Focus, a także Logical Focus...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 ...
Czasami muszę nawet zresetować „IsFocused” na false w ViewModel, jeśli chcę wielokrotnie ustawiać fokus. Ale wtedy to działa, tam gdzie inne metody zawiodły.public bool IsFocused { get { return _isFocused; } set { if (_isFocused == value) { _isFocused = false; OnPropertyChanged(); } _isFocused = value; OnPropertyChanged(); } }
Wiem, że na to pytanie odpowiadano już tysiące razy, ale wprowadziłem kilka zmian we wkładzie Anvaki, które moim zdaniem pomogą innym, którzy mieli podobne problemy, co ja.
Po pierwsze, zmieniłem powyższą załączoną nieruchomość w następujący sposób:
public static class FocusExtension { public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(FocusExtension), new FrameworkPropertyMetadata(IsFocusedChanged){BindsTwoWayByDefault = true}); public static bool? GetIsFocused(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (bool?)element.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject element, bool? value) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(IsFocusedProperty, value); } private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var fe = (FrameworkElement)d; if (e.OldValue == null) { fe.GotFocus += FrameworkElement_GotFocus; fe.LostFocus += FrameworkElement_LostFocus; } if (!fe.IsVisible) { fe.IsVisibleChanged += new DependencyPropertyChangedEventHandler(fe_IsVisibleChanged); } if (e.NewValue != null && (bool)e.NewValue) { fe.Focus(); } } private static void fe_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { var fe = (FrameworkElement)sender; if (fe.IsVisible && (bool)((FrameworkElement)sender).GetValue(IsFocusedProperty)) { fe.IsVisibleChanged -= fe_IsVisibleChanged; fe.Focus(); } } private static void FrameworkElement_GotFocus(object sender, RoutedEventArgs e) { ((FrameworkElement)sender).SetValue(IsFocusedProperty, true); } private static void FrameworkElement_LostFocus(object sender, RoutedEventArgs e) { ((FrameworkElement)sender).SetValue(IsFocusedProperty, false); } }
Powodem dodania odniesień do widoczności były zakładki. Najwyraźniej, jeśli użyłeś dołączonej właściwości na dowolnej innej karcie poza początkowo widoczną kartą, dołączona właściwość nie działała, dopóki nie ustawisz ręcznie formantu.
Inną przeszkodą było stworzenie bardziej eleganckiego sposobu resetowania podstawowej właściwości do wartości false, gdy traci ona ostrość. Tam właśnie pojawiły się wydarzenia związane z utratą ostrości.
<TextBox Text="{Binding Description}" FocusExtension.IsFocused="{Binding IsFocused}"/>
Jeśli istnieje lepszy sposób rozwiązania problemu z widocznością, daj mi znać.
Uwaga: Dziękuję Apfelkuacha za sugestię umieszczenia BindsTwoWayByDefault we właściwości DependencyProperty. Zrobiłem to dawno temu we własnym kodzie, ale nigdy nie aktualizowałem tego postu. Tryb = TwoWay nie jest już potrzebny w kodzie WPF z powodu tej zmiany.
źródło
fe.Dispatcher.BeginInvoke(new Action(() => { fe.Focus(); }), DispatcherPriority.Loaded);
, że jest aktualizowany po załadowaniu. Więcej informacji tutaj: telerik.com/forums/isfocused-property#OXgFYZFOg0WZ2rxidln61QMyślę, że najlepszym sposobem jest utrzymanie zasady MVVM w czystości, więc w zasadzie musisz użyć klasy Messenger dostarczonej z MVVM Light i oto jak z niej korzystać:
in your viewmodel (exampleViewModel.cs): napisz co następuje
Messenger.Default.Send<string>("focus", "DoFocus");
teraz w swoim View.cs (a nie w kodzie XAML the view.xaml.cs) napisz w konstruktorze:
public MyView() { InitializeComponent(); Messenger.Default.Register<string>(this, "DoFocus", doFocus); } public void doFocus(string msg) { if (msg == "focus") this.txtcode.Focus(); }
ta metoda działa dobrze, przy mniejszej ilości kodu i przy zachowaniu standardów MVVM
źródło
Żadne z nich nie działało dokładnie dla mnie, ale dla dobra innych, to właśnie napisałem na podstawie części kodu już tu podanego.
Sposób użycia byłby następujący:
<TextBox ... h:FocusBehavior.IsFocused="True"/>
A realizacja wyglądałaby następująco:
/// <summary> /// Behavior allowing to put focus on element from the view model in a MVVM implementation. /// </summary> public static class FocusBehavior { #region Dependency Properties /// <summary> /// <c>IsFocused</c> dependency property. /// </summary> public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(FocusBehavior), new FrameworkPropertyMetadata(IsFocusedChanged)); /// <summary> /// Gets the <c>IsFocused</c> property value. /// </summary> /// <param name="element">The element.</param> /// <returns>Value of the <c>IsFocused</c> property or <c>null</c> if not set.</returns> public static bool? GetIsFocused(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (bool?)element.GetValue(IsFocusedProperty); } /// <summary> /// Sets the <c>IsFocused</c> property value. /// </summary> /// <param name="element">The element.</param> /// <param name="value">The value.</param> public static void SetIsFocused(DependencyObject element, bool? value) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(IsFocusedProperty, value); } #endregion Dependency Properties #region Event Handlers /// <summary> /// Determines whether the value of the dependency property <c>IsFocused</c> has change. /// </summary> /// <param name="d">The dependency object.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Ensure it is a FrameworkElement instance. var fe = d as FrameworkElement; if (fe != null && e.OldValue == null && e.NewValue != null && (bool)e.NewValue) { // Attach to the Loaded event to set the focus there. If we do it here it will // be overridden by the view rendering the framework element. fe.Loaded += FrameworkElementLoaded; } } /// <summary> /// Sets the focus when the framework element is loaded and ready to receive input. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> private static void FrameworkElementLoaded(object sender, RoutedEventArgs e) { // Ensure it is a FrameworkElement instance. var fe = sender as FrameworkElement; if (fe != null) { // Remove the event handler registration. fe.Loaded -= FrameworkElementLoaded; // Set the focus to the given framework element. fe.Focus(); // Determine if it is a text box like element. var tb = fe as TextBoxBase; if (tb != null) { // Select all text to be ready for replacement. tb.SelectAll(); } } } #endregion Event Handlers }
źródło
To jest stary wątek, ale wydaje się, że nie ma odpowiedzi z kodem, który rozwiązuje problemy z zaakceptowaną odpowiedzią Anavanka: nie działa, jeśli ustawisz właściwość w modelu widoku na fałsz lub ustawisz właściwość na prawda, użytkownik ręcznie klika coś innego, a następnie ponownie ustawiasz wartość true. Również w tych przypadkach nie mogłem sprawić, by rozwiązanie Zamotic działało niezawodnie.
Łącząc niektóre z powyższych dyskusji, otrzymam poniższy kod, który moim zdaniem rozwiązuje te problemy:
public static class FocusExtension { public static bool GetIsFocused(DependencyObject obj) { return (bool)obj.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject obj, bool value) { obj.SetValue(IsFocusedProperty, value); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached( "IsFocused", typeof(bool), typeof(FocusExtension), new UIPropertyMetadata(false, null, OnCoerceValue)); private static object OnCoerceValue(DependencyObject d, object baseValue) { if ((bool)baseValue) ((UIElement)d).Focus(); else if (((UIElement) d).IsFocused) Keyboard.ClearFocus(); return ((bool)baseValue); } }
To powiedziawszy, jest to nadal skomplikowane dla czegoś, co można zrobić w jednym wierszu za kodem, a CoerceValue nie jest tak naprawdę przeznaczone do użycia w ten sposób, więc może być właściwym rozwiązaniem.
źródło
W moim przypadku FocusExtension nie działało, dopóki nie zmienię metody OnIsFocusedPropertyChanged. Oryginalny działał tylko w debugowaniu, gdy punkt przerwania zatrzymał proces. W czasie wykonywania proces przebiega zbyt szybko i nic się nie dzieje. Dzięki tej niewielkiej modyfikacji i pomocy naszego przyjaciela Taska działa to dobrze w obu scenariuszach.
private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var uie = (UIElement)d; if ((bool)e.NewValue) { var action = new Action(() => uie.Dispatcher.BeginInvoke((Action)(() => uie.Focus()))); Task.Factory.StartNew(action); } }
źródło
Problem polega na tym, że gdy IsUserNameFocused jest ustawiona na true, nigdy nie będzie fałszywa. To rozwiązuje problem, obsługując GotFocus i LostFocus dla FrameworkElement.
Miałem problem z formatowaniem kodu źródłowego, więc oto link
źródło
Genialny kod Anvakas jest przeznaczony dla aplikacji Windows Desktop. Jeśli jesteś podobny do mnie i potrzebujesz tego samego rozwiązania dla aplikacji Windows Store, ten kod może być przydatny:
public static class FocusExtension { public static bool GetIsFocused(DependencyObject obj) { return (bool)obj.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject obj, bool value) { obj.SetValue(IsFocusedProperty, value); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached( "IsFocused", typeof(bool), typeof(FocusExtension), new PropertyMetadata(false, OnIsFocusedPropertyChanged)); private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue) { var uie = d as Windows.UI.Xaml.Controls.Control; if( uie != null ) { uie.Focus(FocusState.Programmatic); } } } }
źródło
Dla tych, którzy próbowali użyć powyższego rozwiązania Anvaki, miałem problemy z wiązaniem działającym tylko za pierwszym razem, ponieważ lostfocus nie aktualizował właściwości na false. Możesz ręcznie ustawić właściwość na false, a następnie za każdym razem na true, ale lepszym rozwiązaniem może być zrobienie czegoś takiego w swojej właściwości:
bool _isFocused = false; public bool IsFocused { get { return _isFocused ; } set { _isFocused = false; _isFocused = value; base.OnPropertyChanged("IsFocused "); } }
W ten sposób wystarczy, że ustawisz ją na true, a zostanie ona skupiona.
źródło
Używam WPF / Caliburn Micro i stwierdziłem, że "dfaivre" stworzył ogólne i wykonalne rozwiązanie tutaj: http://caliburnmicro.codeplex.com/discussions/222892
źródło
Znalazłem rozwiązanie, edytując kod w następujący sposób. Nie ma potrzeby ustawiania właściwości Binding najpierw False, a następnie True.
public static class FocusExtension { public static bool GetIsFocused(DependencyObject obj) { return (bool)obj.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject obj, bool value) { obj.SetValue(IsFocusedProperty, value); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached( "IsFocused", typeof(bool), typeof(FocusExtension), new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d != null && d is Control) { var _Control = d as Control; if ((bool)e.NewValue) { // To set false value to get focus on control. if we don't set value to False then we have to set all binding //property to first False then True to set focus on control. OnLostFocus(_Control, null); _Control.Focus(); // Don't care about false values. } } } private static void OnLostFocus(object sender, RoutedEventArgs e) { if (sender != null && sender is Control) { (sender as Control).SetValue(IsFocusedProperty, false); } } }
źródło
W przypadku Silverlight:
using System.Windows; using System.Windows.Controls; using System.Windows.Interactivity; namespace MyProject.Behaviors { public class FocusBehavior : Behavior<Control> { protected override void OnAttached() { this.AssociatedObject.Loaded += AssociatedObject_Loaded; base.OnAttached(); } private void AssociatedObject_Loaded(object sender, RoutedEventArgs e) { this.AssociatedObject.Loaded -= AssociatedObject_Loaded; if (this.HasInitialFocus || this.IsFocused) { this.GotFocus(); } } private void GotFocus() { this.AssociatedObject.Focus(); if (this.IsSelectAll) { if (this.AssociatedObject is TextBox) { (this.AssociatedObject as TextBox).SelectAll(); } else if (this.AssociatedObject is PasswordBox) { (this.AssociatedObject as PasswordBox).SelectAll(); } else if (this.AssociatedObject is RichTextBox) { (this.AssociatedObject as RichTextBox).SelectAll(); } } } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.Register( "IsFocused", typeof(bool), typeof(FocusBehavior), new PropertyMetadata(false, (d, e) => { if ((bool)e.NewValue) { ((FocusBehavior)d).GotFocus(); } })); public bool IsFocused { get { return (bool)GetValue(IsFocusedProperty); } set { SetValue(IsFocusedProperty, value); } } public static readonly DependencyProperty HasInitialFocusProperty = DependencyProperty.Register( "HasInitialFocus", typeof(bool), typeof(FocusBehavior), new PropertyMetadata(false, null)); public bool HasInitialFocus { get { return (bool)GetValue(HasInitialFocusProperty); } set { SetValue(HasInitialFocusProperty, value); } } public static readonly DependencyProperty IsSelectAllProperty = DependencyProperty.Register( "IsSelectAll", typeof(bool), typeof(FocusBehavior), new PropertyMetadata(false, null)); public bool IsSelectAll { get { return (bool)GetValue(IsSelectAllProperty); } set { SetValue(IsSelectAllProperty, value); } } } }
LoginViewModel.cs:
public class LoginModel : ViewModelBase { .... private bool _EmailFocus = false; public bool EmailFocus { get { return _EmailFocus; } set { if (value) { _EmailFocus = false; RaisePropertyChanged("EmailFocus"); } _EmailFocus = value; RaisePropertyChanged("EmailFocus"); } } ... }
Login.xaml:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:beh="clr-namespace:MyProject.Behaviors" <TextBox Text="{Binding Email, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> <i:Interaction.Behaviors> <beh:FocusBehavior IsFocused="{Binding EmailFocus}" IsSelectAll="True"/> </i:Interaction.Behaviors> </TextBox>
LUB
<TextBox Text="{Binding Email, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> <i:Interaction.Behaviors> <beh:FocusBehavior HasInitialFocus="True" IsSelectAll="True"/> </i:Interaction.Behaviors> </TextBox>
Aby ustawić fokus, po prostu zrób to w kodzie:
EmailFocus = true;
Pamiętaj, że ta wtyczka jest częścią strony html, więc inne elementy sterujące na stronie mogą mieć fokus
if (!Application.Current.IsRunningOutOfBrowser) { System.Windows.Browser.HtmlPage.Plugin.Focus(); }
źródło
Możesz użyć wzorca projektowego ViewCommand . Opisuje metodę dla wzorca projektowego MVVM do kontrolowania widoku z ViewModel za pomocą poleceń.
Zaimplementowałem to w oparciu o sugestię Kinga A.Majida, aby użyć klasy MVVM Light Messenger. Klasa ViewCommandManager obsługuje wywoływanie poleceń w połączonych widokach. Zasadniczo jest to inny kierunek zwykłych poleceń w tych przypadkach, gdy ViewModel musi wykonać jakąś akcję w swoim widoku. Używa odbić, takich jak polecenia powiązane z danymi i WeakReferences, aby uniknąć wycieków pamięci.
http://dev.unclassified.de/source/viewcommand (również opublikowane na CodeProject)
źródło
Wydaje się, że nikt nie uwzględnił ostatniego kroku, aby ułatwić aktualizację atrybutów za pomocą powiązanych zmiennych. Oto, co wymyśliłem. Daj mi znać, czy istnieje lepszy sposób na zrobienie tego.
XAML
<TextBox x:Name="txtLabel" Text="{Binding Label}" local:FocusExtension.IsFocused="{Binding txtLabel_IsFocused, Mode=TwoWay}" /> <Button x:Name="butEdit" Content="Edit" Height="40" IsEnabled="{Binding butEdit_IsEnabled}" Command="{Binding cmdCapsuleEdit.Command}" />
ViewModel
public class LoginModel : ViewModelBase { public string txtLabel_IsFocused { get; set; } public string butEdit_IsEnabled { get; set; } public void SetProperty(string PropertyName, string value) { System.Reflection.PropertyInfo propertyInfo = this.GetType().GetProperty(PropertyName); propertyInfo.SetValue(this, Convert.ChangeType(value, propertyInfo.PropertyType), null); OnPropertyChanged(PropertyName); } private void Example_function(){ SetProperty("butEdit_IsEnabled", "False"); SetProperty("txtLabel_IsFocused", "True"); } }
źródło
Po pierwsze, chciałbym podziękować Avance za pomoc w rozwiązaniu mojego problemu z koncentracją. Jest jednak błąd w przesłanym przez niego kodzie, a mianowicie w linii: if (e.OldValue == null)
Problem, jaki miałem, polegał na tym, że jeśli najpierw klikniesz w swoim widoku i ustawiasz ostrość kontrolki, e.oldValue nie jest już zerowa. Następnie, gdy ustawisz zmienną tak, aby skupiła się na kontrolce po raz pierwszy, spowoduje to, że programy obsługi lostfocus i gotfocus nie zostały ustawione. Moje rozwiązanie było następujące:
public static class ExtensionFocus { static ExtensionFocus() { BoundElements = new List<string>(); } public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(ExtensionFocus), new FrameworkPropertyMetadata(false, IsFocusedChanged)); private static List<string> BoundElements; public static bool? GetIsFocused(DependencyObject element) { if (element == null) { throw new ArgumentNullException("ExtensionFocus GetIsFocused called with null element"); } return (bool?)element.GetValue(IsFocusedProperty); } public static void SetIsFocused(DependencyObject element, bool? value) { if (element == null) { throw new ArgumentNullException("ExtensionFocus SetIsFocused called with null element"); } element.SetValue(IsFocusedProperty, value); } private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var fe = (FrameworkElement)d; // OLD LINE: // if (e.OldValue == null) // TWO NEW LINES: if (BoundElements.Contains(fe.Name) == false) { BoundElements.Add(fe.Name); fe.LostFocus += OnLostFocus; fe.GotFocus += OnGotFocus; } if (!fe.IsVisible) { fe.IsVisibleChanged += new DependencyPropertyChangedEventHandler(fe_IsVisibleChanged); } if ((bool)e.NewValue) { fe.Focus(); } } private static void fe_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { var fe = (FrameworkElement)sender; if (fe.IsVisible && (bool)((FrameworkElement)sender).GetValue(IsFocusedProperty)) { fe.IsVisibleChanged -= fe_IsVisibleChanged; fe.Focus(); } } private static void OnLostFocus(object sender, RoutedEventArgs e) { if (sender != null && sender is Control s) { s.SetValue(IsFocusedProperty, false); } } private static void OnGotFocus(object sender, RoutedEventArgs e) { if (sender != null && sender is Control s) { s.SetValue(IsFocusedProperty, true); } } }
źródło
Po prostu zrób to:
<Window x:class... ... ... FocusManager.FocusedElement="{Binding ElementName=myTextBox}" > <Grid> <TextBox Name="myTextBox"/> ...
źródło
Po wdrożeniu zaakceptowanej odpowiedzi natknąłem się na problem polegający na tym, że podczas nawigacji po widokach za pomocą Prism TextBox nadal nie był aktywny. Niewielka zmiana w procedurze obsługi PropertyChanged rozwiązała ten problem
private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var uie = (UIElement)d; if ((bool)e.NewValue) { uie.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => { uie.Focus(); })); } }
źródło
Alternatywne podejście oparte na odpowiedzi @Sheridan tutaj
<TextBox Text="{Binding SomeText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> <TextBox.Style> <Style> <Style.Triggers> <DataTrigger Binding="{Binding SomeTextIsFocused, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="True"> <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}" /> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox>
W modelu widoku skonfiguruj swoje powiązanie w zwykły sposób, a następnie ustaw SomeTextIsFocused na true, aby ustawić fokus na polu tekstowym
źródło
Znalazłem Crucial , że rozwiązanie dotyczące problemu IsVisible jest bardzo przydatne. Nie rozwiązało to całkowicie mojego problemu, ale zrobił to dodatkowy kod zgodny z tym samym wzorcem dla wzorca IsEnabled.
Do metody IsFocusedChanged dodałem:
if (!fe.IsEnabled) { fe.IsEnabledChanged += fe_IsEnabledChanged; }
A oto handler:
private static void fe_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) { var fe = (FrameworkElement)sender; if (fe.IsEnabled && (bool)((FrameworkElement)sender).GetValue(IsFocusedProperty)) { fe.IsEnabledChanged -= fe_IsEnabledChanged; fe.Focus(); } }
źródło
public class DummyViewModel : ViewModelBase { private bool isfocused= false; public bool IsFocused { get { return isfocused; } set { isfocused= value; OnPropertyChanged("IsFocused"); } } }
źródło
System.Windows.Forms.Application.DoEvents(); Keyboard.Focus(tbxLastName);
źródło