2013-04-08 54 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>