2012-05-31 2 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

К сожалению, нет CLR-события для ContentChanged (тем более, что RouteEvent требуется для EventTriggers). Однако, учитывая, что вы имеете дело с настраиваемым элементом управления, вы можете переопределить метаданные для свойства 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

Если вы изменяете выноски 'DependencyObject' в методах' Get..' и 'Set ...' для 'ContentControl', вам не нужно делать проверку типа в методе обратного вызова. – gregsdennis

+2

Отличный пример, приятный и простой .... для новых разработчиков WPF, возможно, стоит добавить xmlns: behavior = "clr-namespace: <ваше пространство имен приложений>" в начало XAML ..... – Monty

+1

Это не поведение, это привязанное свойство. –

Смежные вопросы