2016-11-15 1 views
0

템플릿 컨트롤을 만들고 있습니다. 확장 된 컨트롤을 만드는 것이 아이디어입니다. ContentPresenter에 각각 해당하는 Header 및 Details 속성을 갖습니다. 사용자는 헤더를 탭 할 수 있으며 세부 정보 섹션은 애니메이션으로 확장됩니다. 사용자가 헤더를 다시 탭하면 세부 정보 섹션이 다른 애니메이션과 함께 취소됩니다.템플릿 컨트롤에서 작동하도록 VisualStateGroup.Transitions을 가져올 수 없습니다.

저는 Visual States와 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 애니메이션 같은 것을 사용하고 싶습니다.

상태 사이의 전환이 정상적으로 발생하더라도 문제가 있습니다. 애니메이션은 결코 발생하지 않습니다. 문제를 파악하도록 도와 줄 수 있습니까?

편집 : 여기에 문제는 상태 사이의 전환이 일반적으로 발생에도 불구하고 있다는 것입니다 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

코드입니다. 애니메이션은 결코 발생하지 않습니다. 문제를 파악하도록 도와 줄 수 있습니까?

먼저 컨트롤을하지 않았다에서 VisualState 이름 Compact를 입력하기 때문에 귀하의 VisualTransition From="Compact" To="Expanded"입니다. 그리고 <VisualTransition From="Expanded" To="Compact"> 일 때 DetailsVisibility 속성을 설정하지 않았으므로 마지막 VisualState이 지워지고 접힌 상태로 바로 돌아 가면 애니메이션이 표시되지 않습니다. 여기

나는 코드를 수정하고, 더 분명 페이드 인 및 페이드 아웃의 애니메이션을 만들기 위해, 나는 또한 애니메이션을 변경 :

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); 
} 
:

<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> 

코드가 난 뒤에 수정

렌더링 이미지 :

enter image description here

+0

답변 해 주셔서 감사합니다. 이제 내가 잘못하고있는 것을 봅니다. 나는 당신의 대답을 받아 들일 것이지만 더 나아질 수 있도록 몇 가지 편집을 제안 할 것입니다. – Corcus

+0

@Corcus, 여러분, 환영합니다. 여러분이 아주 잘 만들어 주길 바라고 있습니다. –

관련 문제