Set focus on TextBox in WPF from view model

后端 未结 21 2217
爱一瞬间的悲伤
爱一瞬间的悲伤 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:40

    This is an old thread, but there doesn't seem to be an answer with code that addresses the issues with Anavanka's accepted answer: it doesn't work if you set the property in the viewmodel to false, or if you set your property to true, the user manually clicks on something else, and then you set it to true again. I couldn't get Zamotic's solution to work reliably in these cases either.

    Pulling together some of the discussions above gives me the code below which does address these issues I think:

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

    Having said that, this is still complex for something that can be done in one line in codebehind, and CoerceValue isn't really meant to be used in this way, so maybe codebehind is the way to go.

    0 讨论(0)
  • 2020-11-22 06:40

    Just do this:

    <Window x:class...
       ...
       ...
       FocusManager.FocusedElement="{Binding ElementName=myTextBox}"
    >
    <Grid>
    <TextBox Name="myTextBox"/>
    ...
    
    0 讨论(0)
  • 2020-11-22 06:44

    After implementing the accepted answer I did run across an issue that when navigating views with Prism the TextBox would still not get focus. A minor change to the PropertyChanged handler resolved it

        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();
                }));
            }
        }
    
    0 讨论(0)
  • 2020-11-22 06:46

    An alternative approach based on @Sheridan answer here

     <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>
    

    In your view model set up your binding in the usual way and then set the SomeTextIsFocused to true to set the focus on your text box

    0 讨论(0)
  • 2020-11-22 06:48

    For those trying to use Anvaka's solution above, I was having issues with the binding only working the first time, as lostfocus would not update the property to false. You can manually set the property to false and then true every time, but a better solution could be to do something like this in your property:

    bool _isFocused = false;
        public bool IsFocused 
        {
            get { return _isFocused ; }
            set
            {
                _isFocused = false;
                _isFocused = value;
                base.OnPropertyChanged("IsFocused ");
            }
        }
    

    This way you only ever need to set it to true, and it will get focus.

    0 讨论(0)
  • 2020-11-22 06:50
    public class DummyViewModel : ViewModelBase
        {
            private bool isfocused= false;
            public bool IsFocused
            {
                get
                {
                    return isfocused;
                }
                set
                {
                    isfocused= value;
                    OnPropertyChanged("IsFocused");
                }
            }
        }
    
    0 讨论(0)
提交回复
热议问题