2016-11-15 2 views
0

Я создаю шаблонный элемент управления. Идея состоит в том, чтобы создать расширенный контроль. Он будет иметь свойство заголовка и детали, каждое из которых соответствует ContentPresenter. Пользователь сможет нажать на заголовок, а раздел «Подробности» будет расширяться с помощью анимации. Когда пользователь снова закроет заголовок, раздел «Подробности» вернется с другой анимацией.Не удается получить VisualStateGroup.Transitions для работы в шаблоном управлении

Я использую визуальные состояния и VisualTransitions для достижения этого. Вот мой код.

[TemplatePart(Name ="Header", Type=typeof(ContentPresenter))] 
[TemplatePart(Name = "Details", Type = typeof(ContentPresenter))] 
[TemplateVisualState(GroupName ="ExpandStates",Name ="Expanded")] 
[TemplateVisualState(GroupName = "ExpandStates", Name = "Compact")] 
public sealed class ExpandingItem : Control 
{ 

    private ContentPresenter header; 
    private bool isExpanded; 

    public ExpandingItem() 
    { 
     this.DefaultStyleKey = typeof(ExpandingItem); 
    } 

    public FrameworkElement Header 
    { 
     get { return (FrameworkElement)GetValue(HeaderProperty); } 
     set { SetValue(HeaderProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty HeaderProperty = 
     DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(ExpandingItem), new PropertyMetadata(default(FrameworkElement))); 


    public FrameworkElement Details 
    { 
     get { return (FrameworkElement)GetValue(DetailsProperty); } 
     set { SetValue(DetailsProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for Details. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty DetailsProperty = 
     DependencyProperty.Register("Details", typeof(FrameworkElement), typeof(ExpandingItem), new PropertyMetadata(default(FrameworkElement))); 



    protected override void OnApplyTemplate() 
    { 
     if (header != null) 
     { 
      header.Tapped -= HeaderTapped; 
     } 

     base.OnApplyTemplate(); 

     header = (ContentPresenter)GetTemplateChild("Header"); 
     header.Tapped += HeaderTapped; 
    } 

    private void HeaderTapped(object sender, TappedRoutedEventArgs e) 
    { 
     if (isExpanded) 
     { 
      Retract(); 
      OnStateChanged(new ExpandItemEventArgs(false)); 
     } 
     else 
     { 
      Expand(); 
      OnStateChanged(new ExpandItemEventArgs(true)); 
     } 
     isExpanded = !isExpanded; 
    } 


    public void Expand() 
    { 
     VisualStateManager.GoToState(this, "Expanded", true); 
    } 

    public void Retract() 
    { 
     VisualStateManager.GoToState(this, "Compact", true); 
    } 

    public EventHandler<ExpandItemEventArgs> StateChanged; 
    private void OnStateChanged(ExpandItemEventArgs e) 
    { 
     // Make a temporary copy of the event to avoid possibility of 
     // a race condition if the last subscriber unsubscribes 
     // immediately after the null check and before the event is raised. 
     EventHandler<ExpandItemEventArgs> handler = StateChanged; 

     // Event will be null if there are no subscribers 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 
} 

И шаблон

<Style TargetType="controls:ExpandingItem" > 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="controls:ExpandingItem"> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition Height="Auto"/> 
        </Grid.RowDefinitions> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="ExpandStates"> 
          <VisualStateGroup.Transitions> 
           <VisualTransition From="Compact" To="Expanded"> 
            <VisualTransition.Storyboard> 
             <Storyboard> 
              <FadeInThemeAnimation 
               TargetName="Details"/> 
             </Storyboard> 
            </VisualTransition.Storyboard> 
           </VisualTransition> 
           <VisualTransition From="Expanded" To="Compact"> 
            <VisualTransition.Storyboard> 
             <Storyboard> 
              <FadeOutThemeAnimation 
               TargetName="Details"/> 
             </Storyboard> 
            </VisualTransition.Storyboard> 
           </VisualTransition> 
          </VisualStateGroup.Transitions> 
          <VisualState x:Name="Compact"/> 

          <VisualState x:Name="Expanded"> 
           <VisualState.Setters> 
            <Setter Target="Details.Visibility" Value="Visible"/> 
           </VisualState.Setters> 
           <Storyboard> 
            <FadeInThemeAnimation 
               TargetName="Details"/> 
           </Storyboard> 
          </VisualState> 

         </VisualStateGroup>       
        </VisualStateManager.VisualStateGroups> 


        <ContentPresenter 
         x:Name="Header" 
         Grid.Row="0" 
         Content="{TemplateBinding Header}"/> 

        <ContentPresenter 
         x:Name="Details" 
         Grid.Row="1" 
         Content="{TemplateBinding Details}" 
         Visibility="Collapsed"/> 

       </Grid> 

      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Я использую FadeIn/затухания анимации, как это простой анимации, но в идеале я хотел бы использовать что-то вроде splitopen/splitclose анимации.

Проблема в том, что даже если переход между состояниями происходит нормально. Анимация никогда не возникает. Можете ли вы помочь мне определить проблему?

Edit: Вот код для ExpandItemEventArgs

public class ExpandItemEventArgs : EventArgs 
{ 
    private readonly bool isExpanded; 

    public ExpandItemEventArgs(bool isExpanded) 
    { 
     this.isExpanded = isExpanded; 
    } 

    public bool IsExpanded => isExpanded; 
} 
+0

Как ваш 'ExpandItemEv entArgs'? Можете ли вы опубликовать этот код? –

+0

@ GraceFeng-MSFT Я добавил ExpandItemEventArgs. Однако я не думаю, что они могут повлиять на визуальные состояния. – Corcus

ответ

0

Проблема заключается в том, что даже при том, что переход между состояниями происходит нормально. Анимация никогда не возникает. Можете ли вы помочь мне определить проблему?

Это потому, что ваш VisualTransition From="Compact" To="Expanded", сначала вы не сделали свой контроль введите VisualState с именем Compact. И когда вы <VisualTransition From="Expanded" To="Compact">, так как вы не установили свойство Visibility для своего Details, оно сотрет последние VisualState и вернется в состояние Collapsed напрямую, анимация не будет отображаться.

Здесь я изменил свой код, и для того, чтобы сделать анимацию замирания в и более очевидно, я изменил анимацию также:

<Style TargetType="local:ExpandingItem"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:ExpandingItem"> 
       <Grid Name="RootGrid"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto" /> 
         <RowDefinition Height="Auto" /> 
        </Grid.RowDefinitions> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="ExpandStates"> 
          <VisualStateGroup.Transitions> 
           <VisualTransition To="Expanded" GeneratedDuration="0:0:3"> 
            <Storyboard x:Name="FadeIn"> 
             <DoubleAnimation From="0.1" To="1" Storyboard.TargetProperty="Opacity" 
              Storyboard.TargetName="Details" Duration="0:0:3"> 
              <DoubleAnimation.EasingFunction> 
               <CubicEase /> 
              </DoubleAnimation.EasingFunction> 
             </DoubleAnimation> 
            </Storyboard> 
           </VisualTransition> 
           <VisualTransition From="Expanded" To="Compact" GeneratedDuration="0:0:2.5"> 
            <VisualTransition.Storyboard> 
             <Storyboard x:Name="FadeOut"> 
              <DoubleAnimation From="1" To="0.1" Storyboard.TargetProperty="Opacity" 
               Storyboard.TargetName="Details" Duration="0:0:3"> 
               <DoubleAnimation.EasingFunction> 
                <CubicEase /> 
               </DoubleAnimation.EasingFunction> 
              </DoubleAnimation> 
             </Storyboard> 
            </VisualTransition.Storyboard> 
           </VisualTransition> 
          </VisualStateGroup.Transitions> 

          <VisualState x:Name="Normal"> 
           <VisualState.Setters> 
            <Setter Target="Details.Visibility" Value="Visible" /> 
           </VisualState.Setters> 
          </VisualState> 

          <VisualState x:Name="Compact"> 
           <VisualState.Setters> 
            <Setter Target="Details.Visibility" Value="Collapsed" /> 
           </VisualState.Setters> 
          </VisualState> 

          <VisualState x:Name="Expanded"> 
           <VisualState.Setters> 
            <Setter Target="Details.Visibility" Value="Visible" /> 
           </VisualState.Setters> 
          </VisualState> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 

        <ContentPresenter 
        x:Name="Header" 
        Grid.Row="0" 
        Content="{TemplateBinding Header}" /> 

        <ContentPresenter 
        x:Name="Details" 
        Grid.Row="1" 
        Content="{TemplateBinding Details}" /> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

код я изменил позади:

protected override void OnApplyTemplate() 
{ 
    if (header != null) 
    { 
     header.Tapped -= HeaderTapped; 
    } 

    base.OnApplyTemplate(); 

    VisualStateManager.GoToState(this, "Compact", true); //Go to compact state at first 

    header = (ContentPresenter)GetTemplateChild("Header"); 
    header.Tapped += HeaderTapped; 
} 

public void Expand() 
{ 
    VisualStateManager.GoToState(this, "Normal", true); //Go to Normal state firstly when it expanded, in order to make it visible. 
    VisualStateManager.GoToState(this, "Expanded", true); 
} 

рендеринга изображения:

enter image description here

+0

Спасибо за ваш ответ. Теперь я вижу, что я делаю неправильно. Я приму ваш ответ, но также предложит пару исправлений, чтобы сделать его лучше. – Corcus

+0

@Corcus, добро пожаловать, и это очень мило, что вы редактируете, чтобы сделать его лучше, с нетерпением ждем его. –