2016-05-17 53 views
0

似乎我總是被什麼應該是最簡單的東西難倒...
我有一個用戶控件與自定義bool DependencyProperty'GpoModule'。

默認設置爲false。

當'GpoModule'= true時觸發FadeIn動畫,當'GpoModule'= false時觸發FadeOut動畫。


我的問題是,當控件加載時,FadeOut動畫被觸發,我希望動畫只有在屬性被改變時(或者至少不是在加載時的默認值)才被觸發。我懷疑我可能不得不定義某種事件觸發器,但我希望避免這種情況。

的DependencyProperty:
如何觸發僅依賴於DependencyProperty的動畫(非默認值)?

public bool GpoModule { 
     get { return (bool)GetValue(GpoModuleProperty); } 
     set { SetValue(GpoModuleProperty, value); } 
    } 
    public static readonly DependencyProperty GpoModuleProperty = 
     DependencyProperty.Register("GpoModule", typeof(bool), 
      typeof(ModuleIndicator), new UIPropertyMetadata(false)); 

動畫:

<UserControl.Resources> 
    <Duration x:Key="D">0:0:0.6</Duration> 
    <Storyboard x:Key="SbFadeOut"> 
     <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" 
         From="38" To="0" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
     <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Height)" 
         From="38" 
         To="0" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
     <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" 
         From="1" 
         To="0" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
    </Storyboard> 
    <Storyboard x:Key="SbFadeIn"> 
     <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)" 
         From="0" To="38" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
     <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Height)" 
         From="0" 
         To="38" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
     <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)" 
         From="0" 
         To="1" 
         Duration="{StaticResource D}"> 
      <DoubleAnimation.EasingFunction> 
       <QuadraticEase EasingMode="EaseInOut" /> 
      </DoubleAnimation.EasingFunction> 
     </DoubleAnimation> 
    </Storyboard>   
</UserControl.Resources> 

動畫元素:

<Viewbox x:Name="GpoIndicator" 
      VerticalAlignment="Center" HorizontalAlignment="Center" 
           Stretch="Fill" Width="0" Height="0"> 
     <Grid Height="38" Width="38"> 
      <Ellipse Height="38" 
        Fill="{DynamicResource App.Primary.Light}" 
        Stroke="{DynamicResource App.Border}" /> 
      <TextBlock Width="38" 
        Height="38" 
        Margin="0" 
        HorizontalAlignment="Left" 
        VerticalAlignment="Top" 
        FontFamily="{DynamicResource AppFont}" 
        FontSize="30" 
        FontWeight="Bold" 
        Foreground="{DynamicResource ResourceKey=App.Accent.Secondary}" 
        Padding="0,2,0,0" 
        Text="G" 
        TextAlignment="Center" 
        TextWrapping="Wrap"/> 
     </Grid> 
     <Viewbox.Style> 
      <Style TargetType="Viewbox"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}" 
          Value="True"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard Name="GpoIn"> 
           <Storyboard> 
            <StaticResource ResourceKey="SbFadeIn" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
         <DataTrigger.ExitActions> 
          <RemoveStoryboard BeginStoryboardName="GpoIn" /> 
         </DataTrigger.ExitActions>        
        </DataTrigger> 
        <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}" 
           Value="False"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard Name="GpoOut"> 
           <Storyboard> 
            <StaticResource ResourceKey="SbFadeOut" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
         <DataTrigger.ExitActions> 
          <RemoveStoryboard BeginStoryboardName="GpoOut" /> 
         </DataTrigger.ExitActions> 
        </DataTrigger>      
       </Style.Triggers> 
      </Style> 
     </Viewbox.Style> 
    </Viewbox> 

謝謝!

編輯:我應該提到還有兩個'指標'對象/子項 - 'RedesignIndicator'和'NovellIndicator'。每個都有各自的bool DependencyProperties。
在提出問題之前,我試過使用多個條件。我的第一個嘗試是將條件設置爲「IsLoaded」,但沒有效果。
我的第二次嘗試是使用另一個依賴屬性'AnimationLocked',默認設置爲true,並嘗試了兩個變化。
一:在屬性改變的回調中將AnimationLocked設置爲false(這具有在其他子對象之一上觸發FadeOut動畫的副作用並且在UserControl.Loaded事件中將AnimationLocked設置爲false效果)

+0

的可能重複[我怎樣才能爲在WPF數據觸發多個條件? ](http://stackoverflow.com/questions/905932/how-can-i-provide-multiple-conditions-for-data-trigger-in-wpf),你必須添加另一個條件(另一個依賴屬性'IsLoaded'或者可能已有相關屬性進行檢查) – Sinatr

+0

加載表單始終會導致初始觸發器事件的發生。您可以在構造函數中將屬性設置爲false,然後在表單加載結束時將true設置爲true。然後,所有的方法可以忽略事件,直到屬性設置爲true。 – jdweng

+0

@Sinatr&jdweng:我試過這兩個。我嘗試使用MultiDataTrigger並添加一個條件。一次爲'IsLoaded',一次爲另一個自定義的DependencyProperty'AnimationLocked',它只會在GpoModule屬性發生更改後設置爲false。兩者都具有在不需要的時間禁用或啓用動畫的副作用。 –

回答

0

我最終決定的解決方案是在我的控制下爲三個孩子的「模塊指示符」中的每一個添加一個「AnimationLocked」bool DependencyProperty。 'AnimationLocked'默認爲true,並在'Module'bool DependencyProperty回調中設置爲false,這將確保動畫被阻止,直到通過第一次用戶交互手動更改屬性。我希望有一些內置的方法可以防止觸發器在默認值上「觸發」。這似乎很不雅,我仍然願意接受其他建議。

用戶控件的代碼隱藏:

public bool GpoAnimationLocked 
    { 
     get { return (bool)GetValue(GpoAnimationLockedProperty); } 
     set { SetValue(GpoAnimationLockedProperty, value); } 
    } 
    public static readonly DependencyProperty GpoAnimationLockedProperty = 
     DependencyProperty.Register("GpoAnimationLocked", typeof(bool), 
      typeof(ModuleIndicator), new UIPropertyMetadata(true)); 

    public bool GpoModule { 
     get { return (bool)GetValue(GpoModuleProperty); } 
     set { SetValue(GpoModuleProperty, value); } 
    } 
    public static readonly DependencyProperty GpoModuleProperty = 
     DependencyProperty.Register("GpoModule", typeof(bool), 
      typeof(ModuleIndicator), new UIPropertyMetadata(false, GpoSelectionPropertyChanged)); 

    protected virtual void GpoSelectionChanged(DependencyPropertyChangedEventArgs e) { 
     GpoAnimationLocked = false; 
    } 
    private static void GpoSelectionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { 
     ((ModuleIndicator)sender).GpoSelectionChanged(e); 
    } 

用戶控件的XAML(即動畫孩子「指標」:

<Viewbox x:Name="GpoIndicator" 
      VerticalAlignment="Center" 
      HorizontalAlignment="Center" 
      Stretch="Fill" 
      Width="0" 
      Height="0"> 
     <Grid Height="38" 
       Width="38"> 
      <Ellipse Height="38" 
        Fill="{DynamicResource App.Primary.Light}" 
        Stroke="{DynamicResource App.Border}" /> 
      <TextBlock Width="38" 
         Height="38" 
         Margin="0" 
         HorizontalAlignment="Left" 
         VerticalAlignment="Top" 
         FontFamily="{DynamicResource AppFont}" 
         FontSize="30" 
         FontWeight="Bold" 
         Foreground="{DynamicResource ResourceKey=App.Accent.Secondary}" 
         Padding="0,2,0,0" 
         Text="G" 
         TextAlignment="Center" 
         TextWrapping="Wrap" /> 
     </Grid> 
     <Viewbox.Style> 
      <Style TargetType="Viewbox"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}" 
           Value="True"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard Name="In"> 
           <Storyboard> 
            <StaticResource ResourceKey="SbFadeIn" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 
         <DataTrigger.ExitActions> 
          <RemoveStoryboard BeginStoryboardName="In" /> 
         </DataTrigger.ExitActions> 
        </DataTrigger> 
        <MultiDataTrigger> 
         <MultiDataTrigger.Conditions> 
          <Condition Binding="{Binding GpoAnimationLocked, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}" 
             Value="False" /> 
          <Condition Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}" 
             Value="False" /> 
         </MultiDataTrigger.Conditions> 
         <MultiDataTrigger.EnterActions> 
          <BeginStoryboard Name="Out"> 
           <StaticResource ResourceKey="SbFadeOut" /> 
          </BeginStoryboard> 
         </MultiDataTrigger.EnterActions> 
         <MultiDataTrigger.ExitActions> 
          <RemoveStoryboard BeginStoryboardName="Out" /> 
         </MultiDataTrigger.ExitActions> 
        </MultiDataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Viewbox.Style> 
    </Viewbox> 
0

您可以使用多數據觸發:

<Viewbox.Style> 
    <Style TargetType="Viewbox"> 
     <Style.Triggers> 
      <MultiDataTrigger> 
       <MultiDataTrigger.Conditions> 
        <Condition Binding="{Binding IsLoaded}" Value="True" /> 
        <Condition Binding="{Binding GpoModule}" Value="True" /> 
       </MultiDataTrigger.Conditions> 
       <MultiDataTrigger.EnterAction> 
        ... fade in animation 
       </MultiDataTrigger.EnterAction> 
      </MultiDataTrigger> 
      <MultiDataTrigger> 
       <MultiDataTrigger.Conditions> 
        <Condition Binding="{Binding IsLoaded}" Value="True" /> 
        <Condition Binding="{Binding GpoModule}" Value="False" /> 
       </MultiDataTrigger.Conditions> 
       <MultiDataTrigger.EnterAction> 
        ... fade out animation 
       </MultiDataTrigger.EnterAction> 
      </MultiDataTrigger> 
     </Style.Triggers> 
    </Style> 
</Viewbox.Style> 

IsLoaded是被設定爲true控制Loaded事件處理另一個依賴屬性

這種動畫只會在IsLoaded == true時發生。

P.S .:不確定是否必須在控制Unloaded事件處理程序中設置IsLoaded = false

+0

謝謝你的努力,這或多或少是我已經嘗試過。可以肯定的是,我嘗試了幾種變化 - 我發現在Data/MultiData觸發器設置之前調用了IsLoaded,所以實際上它總是如此。 –

+0

仍然好奇你爲什麼認爲我不應該使用..Trigger.ExitAction? –