2012-05-31 96 views
4

我試圖在內容控件(如Button或ContentControl)更改其內容時觸發動畫。我最初的想法是這樣做的:當ContentControl.Content被改變時開始動畫

 <ContentControl x:Name="ContentElement"> 
      <ContentControl.Style> 
       <Style TargetType="ContentControl"> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate TargetType="ContentControl"> 
           <ContentPresenter x:Name="Content"> 
            <ContentPresenter.Triggers> 
             <EventTrigger RoutedEvent="WHATGOESHERE"> 
              <BeginStoryboard Storyboard="{StaticResource MyAnimation}" Storyboard.TargetName="Content"/> 
             </EventTrigger> 
            </ContentPresenter.Triggers> 
           </ContentPresenter> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </Style> 
      </ContentControl.Style> 

      <Button Content="Hello"/> 
     </ContentControl> 

但我不知道當ContentPresenter更改/更新時會觸發哪個事件。有任何想法嗎?

回答

1

不幸的是,ContentChanged沒有CLR事件(更不用說事件觸發器需要RoutedEvent)。但是,考慮到您正在處理自定義控件,您可以覆蓋Content屬性的元數據並在控件中提供自己的回調。

這可能是你正在尋找here

顯然什麼他創造了一個CLR事件向外部傳播內容的變化;你也可以使用RoutedEvent來代替。

上OverrideMetadata here

9

補充閱讀你可以只寫一個附加屬性:

static class ContentControlExtensions 
{ 
    public static readonly DependencyProperty ContentChangedAnimationProperty = DependencyProperty.RegisterAttached(
     "ContentChangedAnimation", typeof(Storyboard), typeof(ContentControlExtensions), new PropertyMetadata(default(Storyboard), ContentChangedAnimationPropertyChangedCallback)); 

    public static void SetContentChangedAnimation(DependencyObject element, Storyboard value) 
    { 
     element.SetValue(ContentChangedAnimationProperty, value); 
    } 

    public static Storyboard GetContentChangedAnimation(DependencyObject element) 
    { 
     return (Storyboard)element.GetValue(ContentChangedAnimationProperty); 
    } 

    private static void ContentChangedAnimationPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
    { 
     var contentControl = dependencyObject as ContentControl; 
     if (contentControl == null) 
      throw new Exception("Can only be applied to a ContentControl"); 

     var propertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentControl.ContentProperty, 
      typeof (ContentControl)); 

     propertyDescriptor.RemoveValueChanged(contentControl, ContentChangedHandler); 
     propertyDescriptor.AddValueChanged(contentControl, ContentChangedHandler); 
    } 

    private static void ContentChangedHandler(object sender, EventArgs eventArgs) 
    { 
     var animateObject = (FrameworkElement) sender; 
     var storyboard = GetContentChangedAnimation(animateObject); 
     storyboard.Begin(animateObject); 
    } 
} 

,然後在XAML:

 <ContentControl Content="{Binding SelectedViewItem}"> 
      <extensions:ContentControlExtensions.ContentChangedAnimation> 
       <Storyboard> 
        <ThicknessAnimation To="0" From="30,0,-30,0" Duration="0:0:0.3" Storyboard.TargetProperty="Margin"/> 
       </Storyboard> 
      </extensions:ContentControlExtensions.ContentChangedAnimation> 
     </ContentControl> 

這是不是一個新的控制更容易和更短。

+0

如果將'Get..'和'Set ...'方法中的'DependencyObject'標註更改爲'ContentControl',則不需要在回調方法中進行類型檢查。 – gregsdennis

+2

優秀的例子,很好,很簡單....對於新的WPF開發人員來說,它可能只是值得將xmlns:behavior =「clr-namespace:<您的應用程序名稱空間>」添加到XAML的頂部..... – Monty

+1

這不是一種行爲,而是一種附屬財產。 –