2013-10-15 19 views
2

我有一個Stackpanel One,它有一些內容,一個圖像和一個隱藏的SubStackpanel。單擊圖像時,圖像應旋轉90度,然後向下滑動SubStack面板。 當再次點擊圖像時,圖像應該旋轉回原來的位置,並且SubStackpanel應該滑動到默認的隱藏位置。WPF Storyboard - 同樣的觸發器,但是反向行爲

我幾乎得到了這個工作,問題是我不知道如何在兩個不同的Storyboard動畫中使用相同的Trigger事件。所以現在只有按鈕和SubStackPanel中的第一個動畫發生,每次圖像被點擊。 我試過了AutoReverse屬性,但動畫完成後立即激發。這當然應該僅在用戶第二次點擊圖像時發生。

我想實現這一點,只使用標記。

這是我當前的代碼:

<Grid> 
     <StackPanel Grid.Row="0" Orientation="Vertical" Background="Beige" > 
      <StackPanel.Triggers> 
       <EventTrigger SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown"> 
        <BeginStoryboard> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="0" To="66" Duration="0:0:0.5" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger> 
       <EventTrigger SourceName="ImageShowPanelTwo" RoutedEvent="Image.MouseDown"> 
        <BeginStoryboard> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetName="SubPanel" Storyboard.TargetProperty="(StackPanel.Height)" From="66" To="0" Duration="0:0:0.5" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger> 
      </StackPanel.Triggers> 

      <TextBlock>Panel One</TextBlock> 

      <Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png" RenderTransformOrigin=".5,.5" > 
       <Image.RenderTransform> 
        <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" /> 
       </Image.RenderTransform> 
       <Image.Triggers> 
        <EventTrigger RoutedEvent="Image.MouseDown"> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform" 
              Storyboard.TargetProperty="Angle" 
              By="0"   
              To="90" 
              Duration="0:0:0.5" 
               AutoReverse="True"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </EventTrigger> 
        <EventTrigger RoutedEvent="Image.MouseDown"> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation Storyboard.TargetName="AnimatedRotateTransform" 
              Storyboard.TargetProperty="Angle" 
              By="90"   
              To="0" 
              Duration="0:0:0.5" 
               AutoReverse="True"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </EventTrigger> 
       </Image.Triggers> 
      </Image> 


      <StackPanel Name="SubPanel" Background="LightGreen" Height="66"> 
       <TextBlock>SubPanel</TextBlock> 
       <TextBlock>SubPanel</TextBlock> 
      </StackPanel> 

     </StackPanel> 


    </Grid> 

希望你能幫助:)

回答

0

這是我如何解決我的問題:

創建了四個故事板的StackPanel中,箭頭:

<Storyboard x:Key="RotateIconUp"> 
      <DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="0" To="90" Duration="0:0:0.4" /> 
     </Storyboard> 
     <Storyboard x:Key="RotateIconDown"> 
      <DoubleAnimation Storyboard.TargetName="IconExpand" Storyboard.TargetProperty="(TextBlock.RenderTransform).(RotateTransform.Angle)" From="90" To="0" Duration="0:0:0.4" /> 
     </Storyboard> 
     <Storyboard x:Key="SlideGridDown"> 
      <DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="0" To="180" Duration="0:0:0.4" /> 
     </Storyboard> 
     <Storyboard x:Key="SlideGridUp"> 
      <DoubleAnimation Storyboard.TargetName="GridDetails" Storyboard.TargetProperty="(Grid.Height)" From="180" To="0" Duration="0:0:0.4" /> 
     </Storyboard> 

然後,我觸發從代碼隱藏在故事板中單擊箭頭時:

private void ExpandDetails() { 
     try { 
      if (!pm_IsExanded) { 
       Storyboard Storyboard = (Storyboard)FindResource("RotateIconUp"); 
       Storyboard.Begin(this); 
       Storyboard = (Storyboard)FindResource("SlideGridDown"); 
       Storyboard.Begin(this); 
       pm_IsExanded = true; 
       BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#000000") as Brush; 
      } else { 
       Storyboard Storyboard = (Storyboard)FindResource("RotateIconDown"); 
       Storyboard.Begin(this); 
       Storyboard = (Storyboard)FindResource("SlideGridUp"); 
       Storyboard.Begin(this); 
       pm_IsExanded = false; 
       BorderMain.BorderBrush = pm_BrushConverter.ConvertFromString("#d0d0d0") as Brush; 
      } 
     } catch (Exception ee) { 
      GlobalResource.WriteToLog("Error in ExpandDetails", ee); 
     } 
    } 
0

而不是試圖利用這一事件來設置Animation,使用bool屬性綁定到替代:

<Image Name="ImageShowPanelTwo" Width="26" Height="26" Source="ImageRotate.png" 
    RenderTransformOrigin=".5,.5" > 
    <Image.RenderTransform> 
     <RotateTransform x:Name="AnimatedRotateTransform" Angle="0" /> 
    </Image.RenderTransform> 
    <Image.Style> 
     <Style> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding IsRotated}" Value="True"> 
        <DataTrigger.EnterActions> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation 
            Storyboard.TargetName="AnimatedRotateTransform" 
            Storyboard.TargetProperty="Angle" 
            By="0"   
            To="90" 
            Duration="0:0:0.5" 
            AutoReverse="True"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </DataTrigger.EnterActions> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding IsRotated}" Value="False"> 
        <DataTrigger.EnterActions> 
         <BeginStoryboard> 
          <Storyboard> 
           <DoubleAnimation 
            Storyboard.TargetName="AnimatedRotateTransform" 
            Storyboard.TargetProperty="Angle" 
            By="90"   
            To="0" 
            Duration="0:0:0.5" 
            AutoReverse="True"/> 
          </Storyboard> 
         </BeginStoryboard> 
        </DataTrigger.EnterActions> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Image.Style> 
</Image> 

我相信你可以定義你自己的bool屬性並在每個MouseDown事件發生時反轉它完成此功能。因爲它被設置爲true,所以第一個Animation將開始並且因爲它被設置爲false第二個將開始。

+0

非常感謝您的回答! :) 我試過了你的代碼,但是我得到一個錯誤:無法在樣式設置器上設置TargetName屬性。 - 我研究過這個問題,看起來這是一個範圍問題,因爲這是在一種風格中定義的? 此外,我不知道你的解決方案是否可行,因爲我只想在XAML標記中實現這一點。因爲我想在資源中定義這種行爲,並在其他地方使用它。這意味着我不能在代碼隱藏中定義一個bool並將其用作綁定:( – Farsen

+0

啊..我們有兩個問題...首先是'RotateTransform'類沒有'Style'屬性來移動這個動畫,如果你不能定義'bool'屬性,那麼這個方法根本就不起作用。 – Sheridan

+0

嗯,這意味着它不可能爲圖像定義樣式或類似的圖像,使它在點擊時旋轉? – Farsen

3

Blend for Visual Studio可用於以更好,更簡單的方式執行此操作,而無需處理大量代碼。

下面是這樣做的步驟列表。

步驟1:同時在Blend for Visual Studio和Visual Studio中打開項目。

第2步:在Blend中,圍繞您希望用它製作動畫的所有元素創建一個新的故事板。 我們稱之爲「Storyboard1」。

Create a storyboard

步驟3:現在,打開我們剛剛創建的故事板,然後單擊剛剛旁邊的「+」的小箭頭,然後單擊在下拉菜單中選擇「複製」。然後,將創建一個名爲「Storyboard1_Copy」的新故事板。

Duplicating a storyboard

步驟4:重命名這個新的故事板的東西,你喜歡,說: 「Storyboard1_Rev」。

Renaming the newly created storyboard

Storyboard with new name

步驟5:你一定已經猜到了。選擇重複的故事板,然後從下拉菜單中單擊「反轉」。

Reversing the storyboard

步驟6:現在你有兩個故事板準備:一個是動畫的一些元素,你喜歡和其他逆轉動畫的該序列。就像您從C#代碼調用故事板一樣,您可以從相同的調用逆向故事板,但要根據一些檢查元素是否已經動畫的條件進行調用。爲此,我使用了一個bool變量,每次在一組元素上發生動畫時,它的值都會發生變化(即,如果元素尚未動畫,則爲false,如果它們爲真,則爲true)。

插圖用一個例子:

我將創建一個簡單的佈局的應用程序。它在屏幕上有一個按鈕,一個圖像和一個矩形區域。

Initial screen layout

的想法是,只要你點擊按鈕一次,圖像應最大化,並單擊該按鈕兩次,等時,應儘量減少回原來的大小。也就是說,每隔一次單擊按鈕時都會發生逆向動畫。這裏有一些截圖展示它是如何發生的:

Initial Zooming in Zoomed in Zooming out Zoomed out

你可以看到圖像的當前狀態的按鈕顯示。當圖像處於初始小尺寸時顯示「放大」,當圖像最大時顯示「縮小」。

最後,這裏是處理按鈕的點擊的C#代碼:

bool flag = false; 
    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (!flag) 
     { 
      Button.Content = "Zoom Out"; 
      Storyboard1.Begin(); 
      flag = true; 
     } 
     else 
     { 
      Button.Content = "Zoom In"; 
      Storyboard1_Rev.Begin(); 
      flag = false; 
     } 
    } 

所有您需要做的是有顯示的元素(一個或多個)的當前狀態的狀態標誌,你希望根據標誌的值在正向或反向時間線上對其(動作)進行動畫處理和動畫處理。

+0

非常感謝你的努力! – Farsen