2011-11-22 30 views
11

Tôi đang cố tạo mẫu của riêng mình cho điều khiển Expander. Khi điều khiển được mở rộng, tôi muốn nội dung trượt xuống từ từ.Hoàn thành hoạt ảnh "trượt xuống" trong WPF

Chiều cao mong muốn của nội dung không được biết tại thời gian biên dịch.

Tôi nghĩ chúng ta có thể xác định trượt xuống như một phim hoạt hình:

<Storyboard x:Key="ExpandContent"> 

    <DoubleAnimation 
     Storyboard.TargetName="_expanderContent" 
     Storyboard.TargetProperty="Height" 
     From="0.0" 
     To="{Binding ElementName=_expanderContent,Path=DesiredHeight}" 
     Duration="0:0:1.0" /> 
</Storyboard> 

Nhưng Đáng tiếc là không. Chúng tôi gặp lỗi

Không thể cố định cây dòng thời gian Storyboard này để sử dụng trong các chuỗi.

Dường như chúng tôi không thể sử dụng liên kết khi xác định thông số hoạt ảnh. (Cũng thảo luận trong this question.)

Có ai có ý tưởng nào về cách tôi có thể tiếp cận điều này không? Tôi cảnh giác với việc sử dụng LayoutTransform.ScaleY, vì điều đó sẽ tạo ra một hình ảnh méo mó.

Điều này tương tự như this question, nhưng câu hỏi này có câu trả lời liên quan đến viết mã-đằng sau, mà tôi không nghĩ là có thể trong mẫu kiểm soát. Tôi tự hỏi nếu một giải pháp dựa trên XAML có thể đạt được hay không.


Đối với những gì đáng giá, đây là trạng thái hiện tại của mẫu kiểm soát của tôi.

<ControlTemplate x:Key="ExpanderControlTemplate" TargetType="{x:Type Expander}"> 
    <ControlTemplate.Resources> 
      <!-- Here are the storyboards which don't work --> 
      <Storyboard x:Key="ExpandContent"> 

       <DoubleAnimation 
        Storyboard.TargetName="_expanderContent" 
        Storyboard.TargetProperty="Height" 
        From="0.0" 
        To="{Binding ElementName=_expanderContent,Path=DesiredHeight}" 
        Duration="0:0:1.0" /> 
      </Storyboard> 
      <Storyboard x:Key="ContractContent"> 

       <DoubleAnimation 
        Storyboard.TargetName="_expanderContent" 
        Storyboard.TargetProperty="Height" 
        From="{Binding ElementName=_expanderContent,Path=DesiredHeight}" 
        To="0.0" 
        Duration="0:0:1.0" /> 

      </Storyboard> 
     </ControlTemplate.Resources> 
    <Grid Name="MainGrid" Background="White"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Name="ContentRow" Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 
     <Border> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*" /> 
        <ColumnDefinition Width="Auto" /> 
       </Grid.ColumnDefinitions> 
       <ContentPresenter ContentSource="Header" /> 
       <ToggleButton Template="{StaticResource ProductButtonExpand}" 
           Grid.Column="1" 
           IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" 
           /> 
       <Rectangle Grid.ColumnSpan="2" Fill="#FFDADADA" Height="1" Margin="8,0,8,2" VerticalAlignment="Bottom"/> 

      </Grid> 
     </Border> 

      <ContentPresenter Grid.Row="1" HorizontalAlignment="Stretch" Name="_expanderContent"> 

      </ContentPresenter> 

    </Grid> 
    <ControlTemplate.Triggers> 
     <Trigger Property="IsExpanded" Value="True"> 
      <Setter TargetName="_expanderContent" Property="Height" Value="{Binding ElementName=_expanderContent,Path=DesiredHeight}" /> 

       <!-- Here is where I would activate the storyboard if they did work --> 
       <Trigger.EnterActions> 
       <!--<BeginStoryboard Storyboard="{StaticResource ExpandContent}"/>--> 
      </Trigger.EnterActions> 
       <Trigger.ExitActions> 
        <!--<BeginStoryboard x:Name="ContractContent_BeginStoryboard" Storyboard="{StaticResource ContractContent}"/>--> 
       </Trigger.ExitActions> 
     </Trigger> 
      <Trigger Property="IsExpanded" Value="False"> 

       <Setter TargetName="_expanderContent" Property="Height" Value="0" /> 
      </Trigger> 
     </ControlTemplate.Triggers> 

</ControlTemplate> 
+1

Tại sao đặt 'To' và' From' thành DesiredHight? Nếu bạn không đặt chúng, nó sẽ được thực hiện tự động anyway. – icebat

Trả lời

5

Nếu bạn có thể sử dụng Interactions với FluidLayout (Blend 4 SDK), bạn là người may mắn, nó thực sự hữu ích cho những hình ảnh động vật lạ mắt.

Đầu tiên thiết lập Height nội dung CP với tỉ số 0:

<ContentPresenter Grid.Row="1" 
    HorizontalAlignment="Stretch" 
    x:Name="_expanderContent" 
    Height="0"/> 

Để động này, Height chỉ cần được hoạt hình để NaN trong VisualState đại diện cho trạng thái mở rộng (hình ảnh động không rời rạc sẽ không cho phép bạn sử dụng NaN):

xmlns:is="http://schemas.microsoft.com/expression/2010/interactions" 
<Grid x:Name="MainGrid" Background="White"> 
    <VisualStateManager.CustomVisualStateManager> 
     <is:ExtendedVisualStateManager/> 
    </VisualStateManager.CustomVisualStateManager> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="ExpansionStates" is:ExtendedVisualStateManager.UseFluidLayout="True"> 
      <VisualStateGroup.Transitions> 
       <VisualTransition GeneratedDuration="0:0:1"/> 
      </VisualStateGroup.Transitions> 
      <VisualState x:Name="Expanded"> 
       <Storyboard> 
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" 
                Storyboard.TargetName="_expanderContent"> 
         <DiscreteDoubleKeyFrame KeyTime="0" Value="NaN"/> 
        </DoubleAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
      <VisualState x:Name="Collapsed"/> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 
    <!-- ... ---> 

Đó là tất cả những gì cần thiết, cách bố trí chất lỏng sẽ tạo ra sự chuyển đổi cho bạn từ đó.


Nếu bạn có một mã-đằng sau giải pháp đó sẽ là tốt, bạn thậm chí có thể sử dụng mã-đằng sau trong từ điển như thế này:

<!-- TestDictionary.xaml --> 
<ResourceDictionary x:Class="Test.TestDictionary" 
        ...> 
//TestDictionary.xaml.cs 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 

namespace Test 
{ 
    partial class TestDictionary : ResourceDictionary 
    { 
     //Handlers and such here 
    } 
} 
+0

Giải pháp này không hoạt động. NaN vẫn bị phàn nàn. –

+0

@ ChrisBordeman: Vâng, tôi chắc chắn rằng điều này làm việc tại thời điểm viết ... –

4

Đây là loại một tuổi câu hỏi nhưng tôi đã có vấn đề với điều này ngày hôm nay, vì vậy tôi đoán gửi bài giải pháp của tôi sẽ có giá trị nó:

Tôi đã phải làm sống động thuộc tính Chiều cao của một hàng lưới (trượt lên và xuống), nhưng cần có tính năng ràng buộc động để hàng sẽ trượt trở lại vị trí cũ như trước.

Tôi tìm thấy câu trả lời này là rất hữu ích (sau khi vô ích chiến đấu XAML): http://go4answers.webhost4life.com/Question/found-solution-work-protected-override-190845.aspx

điều Đôi khi làm trong code-behind chỉ là đơn giản:

 Storyboard sb = new Storyboard(); 

     var animation = new GridLengthAnimation 
     { 
       Duration = new Duration(500.Milliseconds()), 
       From = this.myGridRow.Height, 
       To = new GridLength(IsGridRowVisible ? GridRowPreviousHeight : 0, GridUnitType.Pixel) 
     }; 

     // Set the target of the animation 
     Storyboard.SetTarget(animation, this.myGridRow); 
     Storyboard.SetTargetProperty(animation, new PropertyPath("Height")); 

     // Kick the animation off 
     sb.Children.Add(animation); 
     sb.Begin(); 

Lớp GridLengthAnimation thể được tìm thấy tại đây: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/da47a4b8-4d39-4d6e-a570-7dbe51a842e4/

+1

Cảm ơn bạn rất nhiều! Cuối cùng, tôi đã nhận được hoạt ảnh tham số của mình. Quả thực nó dường như không thể làm trong XAML. –

+0

Rất vui được điều này. Vâng, phải mất một thời gian để tìm hiểu những điều trong WPF là quá nhiều rắc rối để làm trong XAML và ngược lại;) –

+2

Làm việc tốt! Vì vậy, dễ dàng hơn nhiều so với tất cả các thủ thuật XAML cần thiết để làm điều tương tự. Đối với tất cả các fanVM "không có mã đằng sau" fanatics ra khỏi đó, đây là tất cả mã UI-Only - vượt qua nó. –

0

Có giải pháp chỉ sẵn sàng để sử dụng và XAML on CodeProject:

Các Styles:

<local:MultiplyConverter x:Key="MultiplyConverter" /> 
    <Style TargetType="Expander" x:Key="VerticalSlidingEmptyExpander"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Expander}"> 
        <ScrollViewer x:Name="ExpanderContentScrollView" 
        HorizontalScrollBarVisibility="Hidden" 
        VerticalScrollBarVisibility="Hidden" 
        HorizontalContentAlignment="Stretch" 
        VerticalContentAlignment="Top" 
        > 
         <ScrollViewer.Tag> 
          <system:Double>0.0</system:Double> 
         </ScrollViewer.Tag> 
         <ScrollViewer.Height> 
          <MultiBinding Converter="{StaticResource MultiplyConverter}"> 
           <Binding Path="ActualHeight" ElementName="ExpanderContent"/> 
           <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> 
          </MultiBinding> 
         </ScrollViewer.Height> 
         <ContentPresenter x:Name="ExpanderContent" ContentSource="Content"/> 
        </ScrollViewer> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsExpanded" Value="True"> 
          <Trigger.EnterActions> 
           <BeginStoryboard> 
            <Storyboard> 
             <DoubleAnimation 
         Storyboard.TargetName="ExpanderContentScrollView" 
         Storyboard.TargetProperty="Tag" 
         To="1" 
         Duration="0:0:0.2"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </Trigger.EnterActions> 
          <Trigger.ExitActions> 
           <BeginStoryboard> 
            <Storyboard> 
             <DoubleAnimation 
         Storyboard.TargetName="ExpanderContentScrollView" 
         Storyboard.TargetProperty="Tag" 
         To="0" 
         Duration="0:0:0.2"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </Trigger.ExitActions> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
    <Style TargetType="Expander" x:Key="HorizontalSlidingEmptyExpander"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Expander}"> 
        <ScrollViewer x:Name="ExpanderContentScrollView" 
        HorizontalScrollBarVisibility="Hidden" 
        VerticalScrollBarVisibility="Hidden" 
        HorizontalContentAlignment="Left" 
        VerticalContentAlignment="Stretch" 
        > 
         <ScrollViewer.Tag> 
          <system:Double>0.0</system:Double> 
         </ScrollViewer.Tag> 
         <ScrollViewer.Width> 
          <MultiBinding Converter="{StaticResource MultiplyConverter}"> 
           <Binding Path="ActualWidth" ElementName="ExpanderContent"/> 
           <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> 
          </MultiBinding> 
         </ScrollViewer.Width> 
         <ContentPresenter x:Name="ExpanderContent" ContentSource="Content"/> 
        </ScrollViewer> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsExpanded" Value="True"> 
          <Trigger.EnterActions> 
           <BeginStoryboard> 
            <Storyboard> 
             <DoubleAnimation 
         Storyboard.TargetName="ExpanderContentScrollView" 
         Storyboard.TargetProperty="Tag" 
         To="1" 
         Duration="0:0:0.2"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </Trigger.EnterActions> 
          <Trigger.ExitActions> 
           <BeginStoryboard> 
            <Storyboard> 
             <DoubleAnimation 
         Storyboard.TargetName="ExpanderContentScrollView" 
         Storyboard.TargetProperty="Tag" 
         To="0" 
         Duration="0:0:0.2"/> 
            </Storyboard> 
           </BeginStoryboard> 
          </Trigger.ExitActions> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

MultiplyConverter:

public class MultiplyConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, 
      object parameter, CultureInfo culture) 
    { 
     double result = 1.0; 
     for (int i = 0; i < values.Length; i++) 
     { 
      if (values[i] is double) 
       result *= (double)values[i]; 
     } 

     return result; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, 
      object parameter, CultureInfo culture) 
    { 
     throw new Exception("Not implemented"); 
    } 
} 

tôi nhân đôi Style có một phiên bản theo chiều ngang và dọc và bỏ qua ToggleButtons, nhưng bạn có thể dễ dàng nhận được rằng từ các bài bản gốc.

+0

Sử dụng vấn đề giải pháp này để không có nút chuyển đổi và không có tiêu đề nào cả – igorGIS

Các vấn đề liên quan