microsoft / XamlBehaviors

This is the official home for UWP XAML Behaviors on GitHub.
MIT License
700 stars 112 forks source link

Setting Behaviors via Style getting undesired results #128

Closed SuperJMN closed 5 years ago

SuperJMN commented 7 years ago

Important: See Sample solution below (zipped file)!

I have created a OnEnterFocusNextBehavior that sets the focus to the next element when the user presses the Enter key and I want every TextBox and PasswordBox to have this functionality, by default To do so, I did those Styles

        <Style TargetType="TextBox">
            <Setter Property="i:Interaction.Behaviors">
                <Setter.Value>
                    <i:BehaviorCollection>
                        <app:OnEnterFocusNextBehavior></app:OnEnterFocusNextBehavior>
                    </i:BehaviorCollection>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="PasswordBox">
            <Setter Property="i:Interaction.Behaviors">
                <Setter.Value>
                    <i:BehaviorCollection>
                        <app:OnEnterFocusNextBehavior></app:OnEnterFocusNextBehavior>
                    </i:BehaviorCollection>
                </Setter.Value>
            </Setter>
        </Style>

I put this XAML inside MainPage to test it. However, it only works on the very first TextBox. I have debugged it and the OnAttached method is only called once.

    <StackPanel>
        <TextBox></TextBox>
        <TextBox></TextBox>
        <TextBox></TextBox>
        <TextBox></TextBox>
        <TextBox></TextBox>
    </StackPanel>

This is my custom Behavior

    public class OnEnterFocusNextBehavior : Behavior<UIElement>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.KeyUp += AssociatedObjectOnKeyUp;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.KeyUp -= AssociatedObjectOnKeyUp;
        }

        private void AssociatedObjectOnKeyUp(object sender, KeyRoutedEventArgs keyRoutedEventArgs)
        {
            if (keyRoutedEventArgs.Key == VirtualKey.Enter)
            {
                FocusManager.TryMoveFocus(FocusNavigationDirection.Next);
            }
        }
    }

Am I doing it wrong?

BehaviorInStyleDemo.zip

pedrolamas commented 7 years ago

AFAIK, you can't set a behavior in a style!

Having said that, Cimbalino Toolkit contains an AutoFocusBehavior you can put directly in the root element of your page and it will jump to the next control on Enter!

SuperJMN commented 7 years ago

Thanks for the quick answer! Can this be confirmed by the authors? in case you're not the author of this library :)

pedrolamas commented 7 years ago

I just contribute here but I'm the author of Cimbalino Toolkit (and wrote that specific behavior), so fell free to open an issue in the correct place if you have problems using it! 😄

SuperJMN commented 7 years ago

OK! I hope somebody can confirm it then. I will take a look to the Cimbalino Toolkit, BTW :)

artemious7 commented 7 years ago

We can do this using pure XAML and a reusable attached property, that receives a DataTemplate with a BehaviorCollection (or a single Behavior). You don't have to change your code-behind.

Here's the code

jamers99 commented 5 years ago

Is this going to be fixed?

artemious7 commented 5 years ago

Is this going to be fixed?

I don't think it is a bug. Looks like that's the way Styles work, and XamlBehaviors are designed for elements rather than Styles, which need DataTemplates to make it work. See my answer above for a flexible workaround.