I defined ListBox
in my XAML which uses ItemTemplate
.
Inside the ItemTemplate
I placed Image.
<ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel x:Name="itmTempPanel" IsItemsHost="True" ItemWidth="60" ItemHeight="60" Width="{Binding ElementName=lstFilesDropped, Path=Width}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
<Image>
<Image.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" To="71" Duration="0:0:0.3" />
<DoubleAnimation Storyboard.TargetName="itmTempPanel" Storyboard.TargetProperty="Height" To="71" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</ListBox.ItemTemplate>
When the mouse enter the image I want to begin storyboard on that image height and on the WrapPanel
which I defined inside the ItemsPanelTemplate
.
When the mouse enter to this image I got the following exception: "'itmTempPanel' name cannot be found in the name scope of 'System.Windows.Controls.Image'."
How can I change other element property from element that begin the storyboard.
Thank you for your help !!
There are 2 ways to solve this. The first is using {x:Reference}
a feature in .NET 4.0 for WPF. You should follow this approach if your application targets .NET 4.0. The idea is setting the Storyboard.Target
to the object you want to animate (in this case is the WrapPanel
). Although we can use Binding
for Storyboard.Target
but we cannot use RelativeSource
or ElementName
to set the binding source because Storyboard
(or Timeline) is not a FrameworkElement (or FrameworkContentElement). The only way to specify the source is setting the Source
property. However we can normally set this to a StaticResource
or DynamicResource
or directly (using element syntax). It's fortunate that the {x:Reference}
was introduced in .NET 4.0 and this can help you reference any named object inside XAML (the way it works is not like ElementName
). Here is the code for the first approach:
<DoubleAnimation Storyboard.Target="{Binding Source={x:Reference itmTempPanel}}"
Storyboard.TargetProperty="Height"
To="71" Duration="0:0:0.3" />
The second approach is based on DataTrigger
. However this trigger is not for Image
, it's exactly for the WrapPanel
. But now the ElementName
can be used to bind the Trigger source to the Image
. So this approach is usable when {x:Reference}
is not supported.
<WrapPanel x:Name="itmTempPanel" IsItemsHost="True" ItemWidth="60" ItemHeight="60"
Width="{Binding ElementName=lstFilesDropped, Path=Width}">
<WrapPanel.Style>
<Style TargetType="WrapPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,ElementName=image}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height"
To="71" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</WrapPanel.Style>
</WrapPanel>
<Image Name="image">
<Image.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Height" To="71"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
Note that you have to give the Image
a name (such as image
). The <DoubleAnimation>
for the WrapPanel is removed. Instead of using EventTrigger
, we used DataTrigger
listening to IsMouseOver
property. You can also specify the DataTrigger.ExitActions
to start animating when IsMouseOver
is false (equal to MouseLeave
).