punker76 / MahApps.Metro.SimpleChildWindow

A simple child window for MahApps.Metro
MIT License
374 stars 55 forks source link

Focus textbox on load ChildWindow #89

Closed agustinm20 closed 5 years ago

agustinm20 commented 5 years ago

Hi everyone, I have a ChildWindow, when the user opened the ChildWindow I want to focus on one Textbox.

I tried with textbox1.Focus() and FocusManager.SetFocusedElement(RootGrid2, textbox1);

The focus is set but not active, it's weird.

There is a solution for this?

Thanks in advance.

JohnFredMeyer commented 5 years ago

@agustinm20 its hard to say with information provided. Are you calling items in the code behind of the view? Are you calling code in constructor or Loaded event etc? I can tell you that WPF has some nuances with focus where it is not guaranteed in certain scenarios and if you search StackOverflow you'll see. I can tell you i handle focus completely different in my apps. I found a solution on stack I use in all my projects now. I have a folder in my projects called behaviors where I keep certain items. One of those is a class called Keyboard focus. Here is code.

    public class KeyboardFocus
    {
        public static readonly DependencyProperty OnProperty;

        public static void SetOn(UIElement element, FrameworkElement value)
        {
            element.SetValue(OnProperty, value);
        }

        public static FrameworkElement GetOn(UIElement element)
        {
            return (FrameworkElement) element.GetValue(OnProperty);
        }

        static KeyboardFocus()
        {
            OnProperty = DependencyProperty.RegisterAttached("On", typeof(FrameworkElement), typeof(KeyboardFocus),
                new PropertyMetadata(OnSetCallback));
        }

        private static void OnSetCallback(DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var frameworkElement = (FrameworkElement) dependencyObject;
            var target = GetOn(frameworkElement);

            if (target == null)
                return;

            frameworkElement.Loaded += (s, e) => Keyboard.Focus(target);
        }
    }

Then I have xmlns namespace defined as such in my views.

xmlns:behaviors="clr-namespace:YourProject.Behaviors"

Then on item I want to have focus I do like so.

                    <TextBox Name="NameTextBox"
                             Style="{StaticResource VdiToolKitTextBoxStyle}"
                             behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}">
                        <Binding Path="Name"
                                 Mode="TwoWay"
                                 UpdateSourceTrigger="PropertyChanged">
                            <Binding.ValidationRules>
                                <validation:CharacterLengthValidationRule MaxCharacterLength="255" />
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox>

Main part is the

behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}"

punker76 commented 5 years ago

@agustinm20 Did you tried also the FocusedElement property on the ChildWindow? This allows you to set the focus on any element inside the child window.

agustinm20 commented 5 years ago

@agustinm20 Did you tried also the FocusedElement property on the ChildWindow? This allows you to set the focus on any element inside the child window.

Hi, yes, I tried that, doesn't work.

agustinm20 commented 5 years ago

@agustinm20 its hard to say with information provided. Are you calling items in the code behind of the view? Are you calling code in constructor or Loaded event etc? I can tell you that WPF has some nuances with focus where it is not guaranteed in certain scenarios and if you search StackOverflow you'll see. I can tell you i handle focus completely different in my apps. I found a solution on stack I use in all my projects now. I have a folder in my projects called behaviors where I keep certain items. One of those is a class called Keyboard focus. Here is code.

    public class KeyboardFocus
    {
        public static readonly DependencyProperty OnProperty;

        public static void SetOn(UIElement element, FrameworkElement value)
        {
            element.SetValue(OnProperty, value);
        }

        public static FrameworkElement GetOn(UIElement element)
        {
            return (FrameworkElement) element.GetValue(OnProperty);
        }

        static KeyboardFocus()
        {
            OnProperty = DependencyProperty.RegisterAttached("On", typeof(FrameworkElement), typeof(KeyboardFocus),
                new PropertyMetadata(OnSetCallback));
        }

        private static void OnSetCallback(DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var frameworkElement = (FrameworkElement) dependencyObject;
            var target = GetOn(frameworkElement);

            if (target == null)
                return;

            frameworkElement.Loaded += (s, e) => Keyboard.Focus(target);
        }
    }

Then I have xmlns namespace defined as such in my views.

xmlns:behaviors="clr-namespace:YourProject.Behaviors"

Then on item I want to have focus I do like so.

                    <TextBox Name="NameTextBox"
                             Style="{StaticResource VdiToolKitTextBoxStyle}"
                             behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}">
                        <Binding Path="Name"
                                 Mode="TwoWay"
                                 UpdateSourceTrigger="PropertyChanged">
                            <Binding.ValidationRules>
                                <validation:CharacterLengthValidationRule MaxCharacterLength="255" />
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox>

Main part is the

behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}"

Thanks for the reply! I'll test that soon!

agustinm20 commented 5 years ago

@agustinm20 its hard to say with information provided. Are you calling items in the code behind of the view? Are you calling code in constructor or Loaded event etc? I can tell you that WPF has some nuances with focus where it is not guaranteed in certain scenarios and if you search StackOverflow you'll see. I can tell you i handle focus completely different in my apps. I found a solution on stack I use in all my projects now. I have a folder in my projects called behaviors where I keep certain items. One of those is a class called Keyboard focus. Here is code.

    public class KeyboardFocus
    {
        public static readonly DependencyProperty OnProperty;

        public static void SetOn(UIElement element, FrameworkElement value)
        {
            element.SetValue(OnProperty, value);
        }

        public static FrameworkElement GetOn(UIElement element)
        {
            return (FrameworkElement) element.GetValue(OnProperty);
        }

        static KeyboardFocus()
        {
            OnProperty = DependencyProperty.RegisterAttached("On", typeof(FrameworkElement), typeof(KeyboardFocus),
                new PropertyMetadata(OnSetCallback));
        }

        private static void OnSetCallback(DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var frameworkElement = (FrameworkElement) dependencyObject;
            var target = GetOn(frameworkElement);

            if (target == null)
                return;

            frameworkElement.Loaded += (s, e) => Keyboard.Focus(target);
        }
    }

Then I have xmlns namespace defined as such in my views.

xmlns:behaviors="clr-namespace:YourProject.Behaviors"

Then on item I want to have focus I do like so.

                    <TextBox Name="NameTextBox"
                             Style="{StaticResource VdiToolKitTextBoxStyle}"
                             behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}">
                        <Binding Path="Name"
                                 Mode="TwoWay"
                                 UpdateSourceTrigger="PropertyChanged">
                            <Binding.ValidationRules>
                                <validation:CharacterLengthValidationRule MaxCharacterLength="255" />
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox>

Main part is the

behaviors:KeyboardFocus.On="{Binding RelativeSource={RelativeSource Self}}"

It works perfect! Thanks man!

JohnFredMeyer commented 5 years ago

@agustinm20 No problem.