Logrus
Topic Author
Posts: 30
Joined: 22 Jul 2015, 12:16

Iteraction.Trigger inside DataTemplate

22 Sep 2021, 16:57

Hi
        <DataTemplate DataType="{x:Type SubHierarchy}">
            <TreeView ItemContainerStyle="{StaticResource Style.SceneMultiSelectedTreeViewItem}" ItemsSource="{Binding Root.Childs}">

                <i:Interaction.Behaviors>
                    <TreeViewMultipleSelectionBehavior x:Name="msb" SelectedItems="{Binding SelectedNodes, Mode=TwoWay}" />
                </i:Interaction.Behaviors>

                <i:Interaction.Triggers>
                    <EventTrigger EventName="MultiSelectionChanged" SourceName="msb">
                        <InvokeCommandAction Command="{Binding ChangeSelectedNodesCommand}" />
                    </EventTrigger>
                </i:Interaction.Triggers>

            </TreeView>
        </DataTemplate>
EventTrigger fires if set on the TreeView event.

If bind to TreeViewMultipleSelectionBehavior, then it is not called.

In debug, Trigger binds to event (EventTriggerBase.cpp)
 Noesis::EventHandler& handler = *(Noesis::EventHandler*)event->GetContent(source);
 handler += MakeDelegate(this, &EventTriggerBase::OnDelegateEvent); ///Call 
when called MultiSelectionChanged,
Delegate.Size () is empty
 
Logrus
Topic Author
Posts: 30
Joined: 22 Jul 2015, 12:16

Re: Iteraction.Trigger inside DataTemplate

23 Sep 2021, 09:37

The problem is in Behavior. Handler Binding occurs after
CloneCommonCore(const Freezable* source)
, therefore Handler bind only to source (Behavior) in DataTemplate.

This is how it works, not sure if this is correct
	void TreeViewMultipleSelectionBehavior::CloneCommonCore(const Freezable* source)
	{
		Base::CloneCommonCore(source);
		
		auto behavior = (TreeViewMultipleSelectionBehavior*)source;
		mMultiSelectionChanged = behavior->mMultiSelectionChanged;

		//Store pointer  
		mSourceBehavior = behavior;
	}
	void TreeViewMultipleSelectionBehavior::OnTreeViewItemMouseUp(BaseComponent* sender, const MouseButtonEventArgs& e)
	{
			if (mSourceBehavior) {
				mMultiSelectionChanged = mSourceBehavior->mMultiSelectionChanged;
			}
			mMultiSelectionChanged(this, MultiSelectionChangedEventArgs{ this, MultiSelectionChangedEvent, items });  //Call
		}
	}
 
User avatar
sfernandez
Site Admin
Posts: 2387
Joined: 22 Dec 2011, 19:20

Re: Iteraction.Trigger inside DataTemplate

23 Sep 2021, 11:19

Hi, this problem is related to this know bug: https://www.noesisengine.com/bugs/view.php?id=1476
When template gets applied, the cloned behavior is not properly registered in the namescope, so instead of returning the cloned object, it returns the behavior in the template definition.

Your approach won't work if the DataTemplate is applied to different controls at the same time, because when one of the behaviors raises the event, it will be notified to all the instances.

In the ticket I mentioned we provide a workaround, but this is something we need to fix. We'll try to solve it for next release.
 
Logrus
Topic Author
Posts: 30
Joined: 22 Jul 2015, 12:16

Re: Iteraction.Trigger inside DataTemplate

23 Sep 2021, 12:06

How to bind in this case?
                <i:Interaction.Triggers>
                    <EventTrigger EventName="???" SourceName="msb">
                        <InvokeCommandAction Command="{Binding ChangeSelectedNodesCommand}" />
                    </EventTrigger>
                </i:Interaction.Triggers>
 
User avatar
sfernandez
Site Admin
Posts: 2387
Joined: 22 Dec 2011, 19:20

Re: Iteraction.Trigger inside DataTemplate

23 Sep 2021, 12:39

This should the trick:
<DataTemplate DataType="{x:Type SubHierarchy}">
    <TreeView x:Name="tv" ItemContainerStyle="{StaticResource Style.SceneMultiSelectedTreeViewItem}" ItemsSource="{Binding Root.Childs}">
        <i:Interaction.Behaviors>
            <TreeViewMultipleSelectionBehavior SelectedItems="{Binding SelectedNodes, Mode=TwoWay}" />
        </i:Interaction.Behaviors>
        <i:Interaction.Triggers>
            <EventTrigger EventName="MultiSelectionChanged" SourceObject="{Binding (i:Interaction.Behaviors)[0], ElementName=tv}">
                <InvokeCommandAction Command="{Binding ChangeSelectedNodesCommand}" />
            </EventTrigger>
        </i:Interaction.Triggers>
    </TreeView>
</DataTemplate>
 
Logrus
Topic Author
Posts: 30
Joined: 22 Jul 2015, 12:16

Re: Iteraction.Trigger inside DataTemplate

23 Sep 2021, 13:00

Thanks

Who is online

Users browsing this forum: No registered users and 2 guests