I'm working on a Windows Store App with C# and ran into something where I can't imagine it's difficult, but I can't find out how to do it.
On my MainPage.xaml
I created a user control: A StackPanel
with horizontal orientation, with just an Image
and a TextBlock
inside. Like this:
<!-- language: lang-xml -->
<StackPanel Width="300" Height="100" Orientation="Horizontal" Margin="0,0,0,20" Tapped="LoremIpsum_Tapped">
<Image Source="/Assets/pic.jpg" Margin="20"/>
<TextBlock FontFamily="Segoe UI" FontSize="30" VerticalAlignment="Center">
Lorem Ipsum
</TextBlock>
</StackPanel>
Which looks like this:
I use it as a custom kind of button to get to some sub-page. Now the thing is, there are no animations. I wanted to have the typical animations that ListItem
s have in a SplitView: shrink when pressed, grow back to normal when either released or when the pointer exits the virtual borders of the control. I couldn't find the animation declaration/definition associated with those ListItems (Common.StandardStyles.xaml
Standard130ItemTemplate
). But I found out (here) that there are predefined animations for that: PointerDownThemeAnimation
and PointerUpThemeAnimation
. But then it took me quite a while to find out how to apply them to the control. You might think the sample mentioned on this site specifically about those pointer theme animations (about C#) should help, but it leads to sample for HTML/Javascript animations. But I found solutions here, here and here.
So I needed Storyboard
s in the control resources, a name so the control can be targeted and event handlers in the code-behind.
Applied on my XAML it becomes this:
<!-- language: lang-xml -->
<StackPanel x:Name="LoremIpsum" Width="300" Height="100" Orientation="Horizontal" Margin="0,0,0,20" Tapped="LoremIpsum_Tapped" PointerPressed="LoremIpsum_AnimDown" PointerReleased="LoremIpsum_AnimUp" PointerExited="LoremIpsum_AnimUp">
<Image Source="/Assets/pic.jpg" Margin="20"/>
<TextBlock FontFamily="Segoe UI" FontSize="30" VerticalAlignment="Center">
Lorem Ipsum
</TextBlock>
<StackPanel.Resources>
<Storyboard x:Name="pointerDownStoryboard">
<PointerDownThemeAnimation TargetName="LoremIpsum" />
</Storyboard>
<Storyboard x:Name="pointerUpStoryboard">
<PointerUpThemeAnimation TargetName="LoremIpsum" />
</Storyboard>
</StackPanel.Resources>
</StackPanel>
Plus the additional event handlers in the code-behind:
<!-- language: lang-cs -->
private void Latest_AnimDown(object sender, PointerRoutedEventArgs e)
{
pointerDownStoryboard.Begin();
}
private void Latest_AnimUp(object sender, PointerRoutedEventArgs e)
{
pointerUpStoryboard.Begin();
}
This worked. But... as I have lots of those kind of user controls, I certainly don't want to add all that for every control. As mentioned before the Standard130ItemTemplate
didn't help. So I thought about custom controls. I was hoping I could just define a MyStackPanel
that's nothing but a StackPanel
+ the StoryBoard
s, and that the targeting to the x:Name would work and maybe I could put the event handlers in the LayoutAwarePage code-behind, so all others inherit from it.
I started looking for how to do that and found this sample of how to create custom controls: XAML user and custom controls sample.
There's the custom control in a Generic.xml:
<!-- language: lang-xml -->
xmlns:local="using:UserAndCustomControls">
<Style TargetType="local:BasicCustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BasicCustomControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And a code file, but not code-behind:
<!-- language: lang-cs -->
namespace UserAndCustomControls
{
public sealed class BasicCustomControl : Control
{
public BasicCustomControl()
{
this.DefaultStyleKey = typeof(BasicCustomControl);
}
}
}
But the sample didn't contain anything about animations. So I played around with the example, trying to add the StoryBoard
s to the Border or to the ControlTemplate, adding event handlers to a self created Generic.xaml.cs code-behind. Nothing worked.
Then I found this, but wasn't sure about how and why to put an event handler into the BasicCustomControl
class. I tried it anyway:
In Generic.xaml
:
<!-- language: lang-xml -->
xmlns:local="using:UserAndCustomControls">
<Style TargetType="local:BasicCustomControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BasicCustomControl">
<Border x:Name="Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Border.Resources>
<Storyboard x:Name="pointerDownStoryboard">
<PointerDownThemeAnimation TargetName="Border" />
</Storyboard>
<Storyboard x:Name="pointerUpStoryboard">
<PointerUpThemeAnimation TargetName="Border" />
</Storyboard>
</Border.Resources>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And in BasicCustomControl.cs
:
<!-- language: lang-cs -->
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
((Storyboard)this.Resources["PointerDownThemeAnimation"]).Begin(this);
}
That didn't work. The Begin()
method doesn't take arguments and without the argument the build succeeded, but I got an System.Runtime.InteropServices.COMException when clicking on the control.
Then I found this on SO: How to add XAML storyboard animation to a full blown WPF Custom Control in an XBAP?
This seems to be an interesting solution, but I don't get it. Here's also some description of VisualState stuff for custom controls, but again I don't know how to apply this to my needs: Quickstart: control templates
Now at this point I spent quite some time on this and I'm just thinking that for this simple thing - a simple, even pre-defined animation for a custom control -, there must be a simple solution. I hope I'm just overlooking something and it's not really that complicated.
To sum up the questions:
- Where's the animation of the
Standard130ItemTemplate
defined and "attached" to the template? - Is there a control that I can "inherit" from that behaves the way I want (just those up/down animations on three events)?
- Is there a way to create that kind of control, that I can inherit from - with XAML + Code?
- Is there a way to do this just with XAML? Is this preferable to the former way?
- Is there a simple example or tutorial on this?
- Are there any collections of custom controls that I can download and use? I wasn't able to find any.