EventTriggers inside ControlTemplates - avoiding leaks
Hi guys,
So I'm attempting to fix the last remaining leaks in our game and I can't find a nice solution to the following problem.
So currently I'm using the NsApp EventTrigger inside a ControlTemplate to invoke a custom command action when a bespoke routed event is raised:
The issue is that SourceObject takes a ref counted pointer to the templated parent so it creates a cyclic reference which prevents the custom control from being cleaned up. I've managed to fix this in most other cases by using the NsGui.TriggerAction instead, i.e:
This fixes the bugs and allows me to replace NsApp.EventTrigger so long as the only action I do is BeginStoryboard, StopStoryboard or ControlStoryboard (as those are the only implemented actions which derive from NsGui.TriggerAction).
Is there a replacement for InvokeCommandAction? How would you suggest I go about doing this? Is there any other way for me to reference an event on the control template's templated parent without causing a cyclic dependency? A relative source binding or template binding do not work.
Cheers,
-Steven
So I'm attempting to fix the last remaining leaks in our game and I can't find a nice solution to the following problem.
So currently I'm using the NsApp EventTrigger inside a ControlTemplate to invoke a custom command action when a bespoke routed event is raised:
Code: Select all
<ControlTemplate x:Key="CustomControl.Template" TargetType="{x:Type Namespace:CustomControl}">
<Grid x:Name="Root"
Background="{TemplateBinding Background}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="CustomEvent" SourceObject="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}}">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Namespace:CustomControl}}, Path=(Namespace:CustomControl.CustomAction)}" />
</i:EventTrigger>
<i:EventTrigger EventName="CustomEvent2" SourceObject="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}}">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Namespace:CustomControl}}, Path=(Namespace:CustomControl.CustomAction2)}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
</ControlTemplate>Code: Select all
<ControlTemplate x:Key="CustomControl.Template" TargetType="{x:Type Namespace:CustomControl}">
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Namespace:CustomControl.CustomEvent">
<BeginStoryboard x:Name="CustomEventStoryboard" Storyboard="{StaticResource Storyboard}" />
</EventTrigger>
<EventTrigger RoutedEvent="Namespace:CustomControl.CustomEvent2">
<BeginStoryboard x:Name="CustomEvent2Storyboard" Storyboard="{StaticResource Storyboard}" />
</EventTrigger>
</ControlTemplate.Triggers>
<Grid x:Name="Root"
Background="{TemplateBinding Background}" >
</Grid>
</ControlTemplate>Is there a replacement for InvokeCommandAction? How would you suggest I go about doing this? Is there any other way for me to reference an event on the control template's templated parent without causing a cyclic dependency? A relative source binding or template binding do not work.
Cheers,
-Steven
-
-
sfernandez
Site Admin
- Posts: 3363
- Joined:
Re: EventTriggers inside ControlTemplates - avoiding leaks
Hi Steve,
If the event is going to be raised by the templated parent you should be able to do the same by moving the EventTrigger to the control, using a Style if it needs to be reused:
Hope this helps.
If the event is going to be raised by the templated parent you should be able to do the same by moving the EventTrigger to the control, using a Style if it needs to be reused:
Code: Select all
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="CustomControl.Template" TargetType="{x:Type local:CustomControl}">
<Grid x:Name="Root" Background="{TemplateBinding Background}" .../>
</ControlTemplate>
<Style x:Key="CustomControl.Style" TargetType="{x:Type local:CustomControl}">
<Setter Property="Background" Value="Silver"/>
<Setter Property="Template" Value="{StaticResource CustomControl.Template}"/>
<Setter Property="noesis:StyleInteraction.Triggers">
<Setter.Value>
<noesis:StyleTriggerCollection>
<b:EventTrigger EventName="CustomEvent">
<b:InvokeCommandAction
Command="{Binding (local:CustomControl.CustomAction),
RelativeSource={RelativeSource AncestorType={x:Type local:CustomControl}}}"/>
</i:EventTrigger>
<b:EventTrigger EventName="CustomEvent2">
<b:InvokeCommandAction
Command="{Binding (local:CustomControl.CustomAction2),
RelativeSource={RelativeSource AncestorType={x:Type local:CustomControl}}}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</noesis:StyleTriggerCollection>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<local:CustomControl Width="200" Height="100" Style="{StaticResource CustomControl.Style}"/>
</Grid>Who is online
Users browsing this forum: Bing [Bot] and 4 guests