Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EventTriggerBehavior throws exception with SourceObject="{x:Bind ...}" #89

Closed
Duranom opened this issue Feb 24, 2016 · 3 comments
Closed

Comments

@Duranom
Copy link

Duranom commented Feb 24, 2016

I have noticed that when using EventTriggerBehavior with SourceObject="{x:Bind ...} you must always have an event name that is available in the parent container even if you define because otherwise it will throw an exception as followed:

Cannot add instance of type 'Microsoft.Xaml.Interactions.Core.EventTriggerBehavior' to a collection of type 'Microsoft.Xaml.Interactivity.BehaviorCollection'.

This is because when using {x:Bind ...} the Behavior will set the resolvedSource internally to the parent container, which is resolved by the parent class Behavior because {x:Bind ...} is used.
If you use {Binding ...} this problem will not occur and therefor workaround till the {x:Bind ...} is supported.

The root cause of this is the SourceObjectProperty PropertyMetadata.

Test case:

Xaml:

<Page ... >
    <Grid>
        <Button Name="TestButton" />
        <i:Interaction.Behaviors>
            <!-- Does not work -->
            <c:EventTriggerBehavior SourceObject="{x:Bind TestButton}" EventName="Click" />
            <!-- Does work -->
            <!-- <c:EventTriggerBehavior SourceObject="{Binding ElementName=TestButton}" EventName="Click" /> -->
        </i:Interaction.Behaviors>
    </Grid>
</Page>

The following will then happen in EventTriggerBehavior when the page is being loaded:
1. EventName binding triggering OnEventNameChanged setting the event name
2. OnAttached is triggered and does ReadLocalValue to check against DependencyProperty.UnsetValue, because this is true it sets the resolvedSource to the parent Grid.
3. OnAttached invokes SetResolvedSource which will invoke RegisterEvent because the resolvedSource is not null.
4. RegisterEvent code will throw an exception in because the event cannot be found in the sourceObjectType.

The different between {x:Bind ...} and {Binding ...} is that at 2 that {x:Bind ...} The ReadLocalValue returns in the beginning DependencyProperty.UnsetValue, but with {Binding ...} the value null.

A fix for this issue would be changing the default value of SourceObjectProperty PropertyMetadata with DependencyProperty.UnsetValue.
Or instead of a ReadLocalValue for DependencyProperty.UnsetValue a normal check against null because the target is almost always a binding or code assigned value?

@Duranom Duranom changed the title EventTriggerBehavior throws exception with SourceObject="{x:Bind}" EventTriggerBehavior throws exception with SourceObject="{x:Bind ...}" Feb 24, 2016
@pedrolamas
Copy link
Collaborator

After debugging this, I noticed that the exception you're seeing get raised here and is due to the fact that the EventName property gets set before the SourceObject is.

If instead of throwing an exception we just return from the method, then this works perfectly with x:Bind syntax.

@Duranom
Copy link
Author

Duranom commented Feb 25, 2016

Yes that was came across my mind and seems to be the solution for now.

Of course it would be nice if you got an error if there is no event on the SourceObject and helps with finding an issue faster, but guess due how x:Bind works when not yet processed/executed that is not possible.

@pedrolamas
Copy link
Collaborator

Indeed. I believe that similar issues would be seen for x:DeferLoadStrategy="Lazy" but this change should fix for both scenarios.

LocalJoost added a commit that referenced this issue Feb 25, 2016
Fixed #89: Ensured EventTriggerBehavior supports x:Bind bindings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants