none
Focus textbox after async call RRS feed

  • Question

  • Hi, I have a strange problem. After using an asynchronous call, I can not do focus to a particular control (textbox in this example). If I comment the lines where asynchronous calls, the focus works perfectly. i'm use MVVM Light 5.3.0 Why? Thx!

                    <TextBox Grid.Row="0"
                             Grid.Column="1"
                             utilidades:FocusExtension.IsFocused="{Binding IsFocused}"
                             Text="{Binding Articulo.Codigo, UpdateSourceTrigger=PropertyChanged}" />


            private async void CargarRubros()
            {
                PrepareIsBusy();
    
                ShowIsBusyMessage = true;
    
                ActiveProgressRing = true;
    
                IsBusyCustomMessage("Cargando rubros...");
    
                try
                {
                    Rubros =
                        await
                            Task.Factory.StartNew(() => new ObservableCollection<Rubro>(_rubroService.TodosLosSubrubros()));
    
                    ActiveProgressRing = false;
    
                    if (Rubros.Any())
                    {
                        RubroSeleccionado = Rubros.First();
                    }
                    else
                    {
                        IsBusyInfoMessage("No se encontraron rubros.");
    
                        await Task.Factory.StartNew(() => Thread.Sleep(2000));
                    }
                }
                catch (Exception)
                {
                    IsBusyErrorMessage("Error al intentar obtener los rubros.");
    
                    ActiveProgressRing = false;
    
                    await Task.Factory.StartNew(() => Thread.Sleep(2000));
                }
                finally
                {
                    ShowIsBusyMessage = false;
    
                    ResetMessageAndImage();
    
                    PrepareIsBusy();
    
                    IsFocused = 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, 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;
            }
        }
            private bool _isFocused;
    
            public bool IsFocused
            {
                get { return _isFocused; }
                set
                {
                    _isFocused = value;
                    RaisePropertyChanged("IsFocused");
                }
            }

    NEW

    I share a file with a sample project. I use NET4.0, 4.5 and 4.6.

    With net4 I downloaded the extension "Microsoft.Bcl.Async" to use TaskEx.Run. Also had the same problem with "Task.Factory.StartNew".

    https://mega.nz/#!71UXQLxJ!a87-8v1gDASRQRKOl4LlUGUwDSixrBUYipP2in8mPKA


    • Edited by HajimeSaito Saturday, October 22, 2016 7:14 PM
    Saturday, October 22, 2016 1:27 AM

Answers

  • First of all the TextBox in yourYour TestNET46 sample project doesn't bind to the IsFocused property:

    <TextBox Grid.Row="0"
                             Grid.Column="1"
                             helpers:FocusExtension.IsFocused="{Binding IsFocused}" />

    Second, you could use the dispatcher to call the Focus method once the layout and render has finished. This works:

    private static void OnIsFocusedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var textBox = dependencyObject as TextBox;
                if (textBox == null) return;
                var newValue = (bool)dependencyPropertyChangedEventArgs.NewValue;
                var oldValue = (bool)dependencyPropertyChangedEventArgs.OldValue;
                if (newValue && !oldValue && !textBox.IsFocused)
                    textBox.Dispatcher.BeginInvoke(new Action(() => textBox.Focus()), DispatcherPriority.Loaded);
            }

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Sunday, October 23, 2016 2:18 PM

All replies

  • First of all the TextBox in yourYour TestNET46 sample project doesn't bind to the IsFocused property:

    <TextBox Grid.Row="0"
                             Grid.Column="1"
                             helpers:FocusExtension.IsFocused="{Binding IsFocused}" />

    Second, you could use the dispatcher to call the Focus method once the layout and render has finished. This works:

    private static void OnIsFocusedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                var textBox = dependencyObject as TextBox;
                if (textBox == null) return;
                var newValue = (bool)dependencyPropertyChangedEventArgs.NewValue;
                var oldValue = (bool)dependencyPropertyChangedEventArgs.OldValue;
                if (newValue && !oldValue && !textBox.IsFocused)
                    textBox.Dispatcher.BeginInvoke(new Action(() => textBox.Focus()), DispatcherPriority.Loaded);
            }

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Sunday, October 23, 2016 2:18 PM
  • Perfect! But this brings me another problem, if I want to use "IsFocused = true", when the window is loaded, it does not work :(.
    Saturday, October 29, 2016 11:29 PM
  • In our case DispatcherPriority.Loaded not always working. Need to change to DispatcherPriority.SystemIdle. Not sure why but at least it works lol

    Hello World

    Tuesday, January 21, 2020 6:59 PM