2013-04-08 12 views
5

Pracuję nad aplikacją Windows Store z C# i wpadłem na coś, czego nie mogę sobie wyobrazić, jest to trudne, ale nie mogę się dowiedzieć, jak to zrobić.XAML - Prosta animacja do prostego sterowania niestandardowego

Na moim MainPage.xaml utworzyłem kontrolkę użytkownika: A StackPanel w orientacji poziomej, z tylko Image i TextBlock w środku. Tak:

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

który wygląda tak:

enter image description here

używam go jako niestandardowego typu przycisk, aby dostać się do jakiejś podstronie. Teraz jest bez animacji. Chciałem mieć typowe animacje, które mają w SplitView: zmniejszanie po naciśnięciu, powrót do normalnego po zwolnieniu lub gdy wskaźnik opuszcza wirtualne granice kontrolki. Nie mogłem znaleźć deklaracji animacji/definicji związanej z tymi ListItems (Common: StandardStyles.xamlStandard130ItemTemplate). Ale dowiedziałem się (here), że istnieją predefiniowane animacje do tego: PointerDownThemeAnimation i PointerUpThemeAnimation. Ale potem zajęło mi trochę czasu, aby dowiedzieć się, jak zastosować je do kontroli. Możesz pomyśleć, że próbka wspomniana na this site specifically about those pointer theme animations (o C#) powinna pomóc, ale prowadzi do sample for HTML/Javascript animations. Ale znalazłem rozwiązania here, here i here.

Potrzebowałem więc Storyboard s w zasobach kontrolnych, nazwy, dzięki czemu kontrola może być ukierunkowana i obsługa zdarzeń w kodzie z tyłu.

stosowane na moim XAML staje się w ten sposób:

<!-- 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 dodatkowe obsługi zdarzeń w opóźnieniem kodu:

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

To działało. Ale ... ponieważ mam wiele takich kontrolek użytkownika, na pewno nie chcę dodawać wszystkiego dla każdej kontroli. Jak wspomniano wcześniej, Standard130ItemTemplate nie pomogło. Więc pomyślałem o niestandardowych kontrolach. Miałem nadzieję, że mogę zdefiniować tylko MyStackPanel, to tylko StackPanel + StoryBoard s i że kierowanie do x: Nazwa będzie działało i może mógłbym umieścić procedury obsługi zdarzeń w kodzie LayoutAwarePage z tyłu, więc wszystkie inne dziedziczą po to.

Zacząłem szukać, jak to zrobić i znalazłem tę próbkę tworzenia niestandardowych formantów: XAML user and custom controls sample.

Jest kontrola zwyczaj w 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> 

i plik kodu, ale nie kod z opóźnieniem:

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

Ale próbka nie zawierała nic na temat animacji. Więc bawiłem się przykładem, próbując dodać StoryBoard s do granicy lub do ControlTemplate, dodając procedury obsługi zdarzeń do stworzonego przez siebie kodu generic.xaml.cs. Nic nie działało.

Następnie znalazłem this, ale nie byłem pewien, jak i dlaczego umieścić obsługę zdarzeń w klasie BasicCustomControl. Próbowałem to tak:

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

I BasicCustomControl.cs:

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

To nie działa. Metoda Begin() nie pobiera argumentów i bez argumentu kompilacja się powiodła, ale po kliknięciu kontrolki dostałem wyjątek System.Runtime.InteropServices.COMEx.

Potem znalazłem to na SO: How to add XAML storyboard animation to a full blown WPF Custom Control in an XBAP?

To wydaje się być ciekawym rozwiązaniem, ale nie rozumiem. Oto także opis rzeczy VisualState dla niestandardowych formantów, ale znowu nie wiem, jak zastosować to do moich potrzeb: Quickstart: control templates

W tym momencie spędziłem trochę czasu nad tym i po prostu myślę, że dla to proste, prosta rzecz: - prosta, nawet predefiniowana animacja dla niestandardowego sterowania -, musi być proste rozwiązanie. Mam nadzieję, że właśnie coś przeoczyłem i to nie jest aż tak skomplikowane.

Podsumowując pytania:

  1. Gdzie jest animacja Standard130ItemTemplate zdefiniowane i „dołączone” do szablonu?
  2. Czy istnieje kontrola, którą mogę "odziedziczyć" po tym, który zachowuje się tak, jak chcę (tylko animacje w górę/w dół na trzech wydarzeniach)?
  3. Czy istnieje sposób na stworzenie tego rodzaju kontroli, którą mogę dziedziczyć po - za pomocą kodu XAML +?
  4. Czy istnieje sposób, aby to zrobić tylko z XAML? Czy jest to lepsze od poprzedniego sposobu?
  5. Czy istnieje prosty przykład lub samouczek na ten temat?
  6. Czy są jakieś kolekcje niestandardowych elementów sterujących, które można pobrać i używać? Nie byłem w stanie znaleźć żadnego.

Odpowiedz

0

Utwórz niestandardowy styl. W tym przykładzie ograniczam źródło obrazu do pola treści. Musiałem więc umieścić moją ścieżkę do mojego obrazu w tym polu (np. "Assets/Image.png"). Byłoby miło, gdyby dodawanie niestandardowych animacji było łatwiejsze do zrozumienia za pierwszym razem.

<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> 
Powiązane problemy