I have a grid which, when hovered over with the mouse, makes one of its child elements come to life (opacity from 0 to 1) but that grid also can be disposed of (that grid is part of a listbox that can be remove via a close button on the grid).
When the user clicks the remove button it also launches the MouseLeave event below which of course can not find my DockStackPanel control anymore since it was disposed. How can I fix this issue?
<Grid.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="DockStackPanel" Storyboard.TargetProperty="Opacity" To="1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.5" Storyboard.TargetName="DockStackPanel" Storyboard.TargetProperty="Opacity" To="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
Have you tried creating the animation in code instead. I'm assuming here that the DockStackPanel control is a StackPanel.
public MainWindow()
{
InitializeComponent();
MyGrid.MouseEnter += MyGrid_MouseEnter;
MyGrid.MouseLeave += MyGrid_MouseLeave;
}
void MyGrid_MouseLeave(object sender, MouseEventArgs e)
{
if (DockStackPanel != null)
{
var dur = new Duration(new TimeSpan(0, 0, 0, 0, 500));
var anim = new DoubleAnimation(0, dur);
DockStackPanel.BeginAnimation(StackPanel.OpacityProperty, anim);
}
}
void MyGrid_MouseEnter(object sender, MouseEventArgs e)
{
var dur = new Duration(new TimeSpan(0, 0, 0, 0, 500));
var anim = new DoubleAnimation(1, dur);
DockStackPanel.BeginAnimation(StackPanel.OpacityProperty, anim);
}
Another thing that you can do is implement DataTrigger
for Grid
which will override default MouseLeave
and MouseEnter
events to do nothing when DisableTriggers
property changed.
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding DisableTriggers}" Value="True">
<Setter Property="Style" Value="{StaticResource GridStyleWithoutStoryboards}" />
</DataTrigger>
</Style.Triggers>
</Style>
This is the case when you don't want to use AttachedBehaviors
. Otherwise I suggest to handle storyboards cleanup in behavior. It is much easier:
void OnDisableTriggersPropertyChanged( object sender, EventArgs args )
{
// If IsDisposed property was changed and it is true now - cleanup triggers.
if ((bool)args.NewValue)
{
var grid = (Grid)sender;
// Ideally you can remove specific triggers.
// Clear all will work for simple cases.
grid.Triggers.Clear();
}
}
So summing up you will have to add attached behavior with DisableTriggers
dependency property which performs cleanup action in OnChanged
handler.
If you want to unsubscribe only from specific events:
foreach (var eventToUnsubscribe in grid.Triggers.OfType<EventTrigger>()
.Where(x => x.RoutedEvent == UIElement.MouseEnterEvent
|| x.RoutedEvent == UIElement.MouseLeaveEvent).ToList())
{
grid.Triggers.Remove(eventToUnsubscribe);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With