2013-04-08 53 views
5

我工作在Windows Store应用与C#简单的动画,跑进一些地方我无法想象这是困难的,但我不能找出如何做到这一点。XAML - 简单的自定义控件

在我MainPage.xaml我创建了一个用户控制:StackPanel与水平方向,只有一个ImageTextBlock内。就像这样:

<!-- 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> 

,看起来像这样:

enter image description here

我用它作为一种定制的按钮来获得一些子页面。现在的事情是,有没有动画。我想要在SplitView中使用ListItem的典型动画:按下时收缩,在释放时或指针退出控件的虚拟边框时恢复正常。我找不到与这些ListItems相关的动画声明/定义(通用。StandardStyles.xamlStandard130ItemTemplate)。但我发现(here),有针对预定义的动画:PointerDownThemeAnimationPointerUpThemeAnimation。但是后来花了我很长时间才弄清楚如何将它们应用于控制。您可能认为this site specifically about those pointer theme animations(约C#)上提到的示例应该有所帮助,但它会导致sample for HTML/Javascript animations。但我发现解决方案hereherehere

所以,我需要Storyboard S IN控制资源,一个名称,以便控制可以有针对性,并在事件处理代码隐藏。

应用在我的XAML就成了这样:

<!-- 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> 

加上额外的事件处理程序中的代码隐藏:

<!-- language: lang-cs --> 
private void Latest_AnimDown(object sender, PointerRoutedEventArgs e) 
{ 
    pointerDownStoryboard.Begin(); 
} 
private void Latest_AnimUp(object sender, PointerRoutedEventArgs e) 
{ 
    pointerUpStoryboard.Begin(); 
} 

这个工作。但是...因为我有很多这样的用户控件,我当然不想为每个控件添加所有这些。如前所述,Standard130ItemTemplate没有帮助。所以我想到了自定义控件。我希望我可以定义一个MyStackPanel这不过是一个StackPanel +的StoryBoard S,并且瞄准到x:名称会工作,也许我可以把事件处理程序的LayoutAwarePage代码隐藏,因此所有其他人继承它。

我开始寻找如何做到这一点,并找到了如何创建自定义控制该样本:XAML user and custom controls sample

有一个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> 

和代码文件,但没有后台代码:

<!-- language: lang-cs --> 
namespace UserAndCustomControls 
{ 
    public sealed class BasicCustomControl : Control 
    { 
     public BasicCustomControl() 
     { 
      this.DefaultStyleKey = typeof(BasicCustomControl); 
     } 
    } 
} 

但样本并没有包含有关动画的东西。所以我打得四处的例子,试图将StoryBoard s添加到边境或到控件模板,添加事件处理程序创建Generic.xaml.cs代码隐藏自我。没有工作。

然后我发现this,但不确定如何以及为什么要将事件处理程序放入BasicCustomControl类。我尝试也无妨:

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> 

而且在BasicCustomControl.cs

<!-- language: lang-cs --> 
protected override void OnPointerPressed(PointerRoutedEventArgs e) 
{ 
    ((Storyboard)this.Resources["PointerDownThemeAnimation"]).Begin(this); 
} 

这没有奏效。 Begin()方法不带参数,没有参数的构建成功,但是当点击控件时我得到了一个System.Runtime.InteropServices.COMException。

然后我发现这对SO:How to add XAML storyboard animation to a full blown WPF Custom Control in an XBAP?

这似乎是一个有趣的解决方案,但我不明白这一点。这里还有一些关于VisualState的自定义控件的说明,但是我不知道如何将它应用于我的需求:Quickstart: control templates

现在我在这一点上花了很长时间,我只是想这个简单的东西 - 一个简单的,甚至是自定义控件的预定义动画 - ,必须有一个简单的解决方案。我希望我只是忽略了一些东西,而这并不是那么复杂。

要总结的问题:

  1. 在哪儿定义的Standard130ItemTemplate的动画和“附加”的模板?
  2. 有没有一种控制方式可以“继承”它的行为方式(我只是希望这些上/下三个动画的动画)?
  3. 有没有办法创建这种控件,我可以继承 - 用XAML + Code?
  4. 有没有办法用XAML来做到这一点?这比以前的方式更可取吗?
  5. 有没有一个简单的例子或教程呢?
  6. 是否有任何我可以下载和使用的自定义控件集合?我无法找到任何。

回答

0

创建自定义样式。在这个例子中,我将图像源绑定到内容字段。所以我只好把自己的道路放在那个领域的形象(例如“Assets/Image.png”)。如果像这样添加自定义动画更容易第一次弄清楚会更好。

<Style x:Key="ImageButtonStyle" TargetType="ButtonBase"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="ButtonBase"> 
       <Grid x:Name="RootGrid" Background="Transparent"> 
        <Image x:Name="ImageLabel" Source="{TemplateBinding Content}"/> 
        <Rectangle 
          x:Name="FocusVisualWhite" 
          IsHitTestVisible="False" 
          Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" 
          StrokeEndLineCap="Square" 
          StrokeDashArray="1,1" 
          Opacity="0" 
          StrokeDashOffset="1.5"/> 
        <Rectangle 
          x:Name="FocusVisualBlack" 
          IsHitTestVisible="False" 
          Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" 
          StrokeEndLineCap="Square" 
          StrokeDashArray="1,1" 
          Opacity="0" 
          StrokeDashOffset="0.5"/> 

        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="CommonStates"> 
          <VisualState x:Name="Normal"/> 
          <VisualState x:Name="PointerOver"> 
          </VisualState> 
          <VisualState x:Name="Pressed"> 
           <Storyboard> 
            <PointerDownThemeAnimation TargetName="ImageLabel" /> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Disabled"> 
          </VisualState> 
         </VisualStateGroup> 
         <VisualStateGroup x:Name="FocusStates"> 
          <VisualState x:Name="Focused"> 
           <Storyboard> 
            <DoubleAnimation 
              Storyboard.TargetName="FocusVisualWhite" 
              Storyboard.TargetProperty="Opacity" 
              To="1" 
              Duration="0"/> 
            <DoubleAnimation 
              Storyboard.TargetName="FocusVisualBlack" 
              Storyboard.TargetProperty="Opacity" 
              To="1" 
              Duration="0"/> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Unfocused" /> 
          <VisualState x:Name="PointerFocused" /> 
         </VisualStateGroup> 
         <VisualStateGroup x:Name="CheckStates"> 
          <VisualState x:Name="Checked"> 
           <Storyboard> 
            <DoubleAnimation Duration="0" To="0" Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Opacity"/> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundCheckedGlyph" Storyboard.TargetProperty="Visibility"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundThemeBrush}"/> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Unchecked"/> 
          <VisualState x:Name="Indeterminate"/> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style>