Set focus on TextBox in WPF from view model

后端 未结 21 2261
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-22 06:21

I have a TextBox and a Button in my view.

Now I am checking a condition upon button click and if the condition turns out to be false, displ

21条回答
  •  醉酒成梦
    2020-11-22 06:51

    I know this question has been answered a thousand times over by now, but I made some edits to Anvaka's contribution that I think will help others that had similar issues that I had.

    Firstly, I changed the above Attached Property like so:

    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);
        }
    }
    

    My reason for adding the visibility references were tabs. Apparently if you used the attached property on any other tab outside of the initially visible tab, the attached property didn't work until you manually focused the control.

    The other obstacle was creating a more elegant way of resetting the underlying property to false when it lost focus. That's where the lost focus events came in.

    
    

    If there's a better way to handle the visibility issue, please let me know.

    Note: Thanks to Apfelkuacha for the suggestion of putting the BindsTwoWayByDefault in the DependencyProperty. I had done that long ago in my own code, but never updated this post. The Mode=TwoWay is no longer necessary in the WPF code due to this change.

提交回复
热议问题