Search code examples
xamluwp

uwp define eventriggerbehavior inside style


I'm currently stuck with a problem. I want to declare a eventriggerbehavior for all my listviews. this is my code:

<Style TargetType="ListView">
            <Setter Property="ItemTemplate" Value="{StaticResource itemShowTemplate}" />
            <i:Interaction.Behaviors>
                <Interactions:EventTriggerBehavior EventName="ItemClicked">
                    <Interactions:InvokeCommandAction Command="{Binding ShowItemClickedCommand}" />
                </Interactions:EventTriggerBehavior>
            </i:Interaction.Behaviors>
</Style>

the problem I have now is that EventTriggerBehavior is looking for the event on Style and not the targettype of Listview. And the only property left to set on EventTriggerBehavior is SourceObject. But I don't want this behavior on 1 listview, I want it on al my listviews.

Is there a way todo this?


Solution

  • My first idea was that it could work this way:

    <Style TargetType="Button">
        <Setter Property="i:Interaction.Behaviors">
            <Setter.Value>
                <i:BehaviorCollection>
                    <core:EventTriggerBehavior EventName="Click">
                        <core:InvokeCommandAction Command="{Binding TestCommand}" />
                    </core:EventTriggerBehavior>
                </i:BehaviorCollection>
            </Setter.Value>
        </Setter>
    </Style>
    

    But unfortunately this works only for the first control which gets the behavior attached. The reason is that the value is constructed just once and the AssociatedObject property of the BehaviorCollection is set to the first control.

    I have then come over this solution - How to add a Blend Behavior in a Style Setter . The idea is to create an attached property that manually assigns the behavior to the control.

    Based on this I suggest you do it like this:

    public static class ListViewBehaviorAttacher
    {
        public static readonly DependencyProperty IsAttachedProperty = DependencyProperty.RegisterAttached(
            "IsAttached", typeof(bool), typeof(ListViewBehaviorAttacher), new PropertyMetadata(default(bool), IsAttachedChanged));
    
        private static void IsAttachedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var listView = (ListView)dependencyObject;
            //create the binding
            BehaviorCollection collection = new BehaviorCollection();
            var eventTrigger = new EventTriggerBehavior() { EventName = "ItemClick" };
            var invokeCommandAction = new InvokeCommandAction();
            //binding to command
            BindingOperations.SetBinding(
                invokeCommandAction,
                InvokeCommandAction.CommandProperty,
                new Binding() { Path = new PropertyPath("ShowItemClickedCommand"), Source = listView.DataContext });
            eventTrigger.Actions.Add(invokeCommandAction);
            collection.Add(eventTrigger);
            listView.SetValue(Interaction.BehaviorsProperty, collection);
        }
    
        public static void SetIsAttached(DependencyObject element, bool value)
        {
            element.SetValue(IsAttachedProperty, value);
        }
    
        public static bool GetIsAttached(DependencyObject element)
        {
            return (bool)element.GetValue(IsAttachedProperty);
        }
    }
    

    And then in the style attach it like this:

    <Style TargetType="ListView">
       <Setter Property="SelectionMode" Value="None"></Setter>
       <Setter Property="IsItemClickEnabled" Value="True" /> 
       <Setter Property="local:ListViewBehaviorAttacher.IsAttached" Value="True" />
    </Style>