[Silverlight] 讓Silverlight的Grid容器的Row Height或是Column Width可以套用動畫

動態的改變Row或Column的大小應該是常常要用到的功能,可是Silverlight又不能像WPF一樣自訂一個新的GridLength動畫出來,那~~只好用騙的了!!
我們可以透過一個型別為double的DependencyProperty來套用DoubleAnimation,並且在它的值改變的時候,利用程式將它轉為GridLength,這樣就可以做到我們要的效果了。


動態的改變Row或Column的大小應該是常常要用到的功能,可是Silverlight又不能像WPF一樣自訂一個新的GridLength動畫出來,那~~只好用騙的了!!
我們可以透過一個型別為double的DependencyProperty來套用DoubleAnimation,並且在它的值改變的時候,利用程式將它轉為GridLength,這樣就可以做到我們要的效果了。

來個範例:

 

程式碼如下:

MainPage.xaml
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Name="MainPageControl"
    x:Class="Sl_GridLengthAnimation.MainPage"
    d:DesignWidth="640" d:DesignHeight="480"
    Width="Auto" Height="Auto">
    
    <UserControl.Resources>
        <Storyboard x:Key="ShowColumn">
            <DoubleAnimation Storyboard.TargetName="MainPageControl" Storyboard.TargetProperty="GridWidth" From="0" To="200" 
                             BeginTime="0:0:0" Duration="0:0:.5" Completed="DoubleAnimation_Completed">
                <DoubleAnimation.EasingFunction>
                    <BounceEase EasingMode="EaseOut"></BounceEase>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
        <Storyboard x:Key="HideColumn">
            <DoubleAnimation Storyboard.TargetName="MainPageControl" Storyboard.TargetProperty="GridWidth" From="200" To="0" 
                             BeginTime="0:0:0" Duration="0:0:.5" Completed="DoubleAnimation_Completed">
                <DoubleAnimation.EasingFunction>
                    <BounceEase EasingMode="EaseOut"></BounceEase>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </UserControl.Resources>
 
        <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="column1" Width="200"/>
            <ColumnDefinition Width="0.75*"/>
        </Grid.ColumnDefinitions>
        <Button Name="btnShowHide" Content="Hide Column" HorizontalAlignment="Center" VerticalAlignment="Center" Width="Auto" 
                             Grid.Column="1" Margin="0,0,8,8" Click="btnShowHide_Click" RenderTransformOrigin="0.5,0.5"
                Padding="10">
            <Button.RenderTransform>
                <CompositeTransform/>
            </Button.RenderTransform>
        </Button>
        <Rectangle Fill="#FF29A7FF"/>
        <TextBlock Text="我在Column1裡面" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" />
    </Grid>
</UserControl>



MainPage.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
 
namespace Sl_GridLengthAnimation
{
    public partial class MainPage : UserControl
    {
        private bool _isColumnCollapsed = false;
 
        public MainPage()
        {
            InitializeComponent();
        }
 
        public static readonly DependencyProperty GridWidthProperty = DependencyProperty.Register( "GridWidth" , typeof( double ) , typeof( MainPage ) ,
            new PropertyMetadata( ( double ) 100.00 , OnGridWidthPropertyChanged ) );
 
        public double GridWidth
        {
            get
            {
                return ( double ) GetValue( GridWidthProperty );
            }
            set
            {
                SetValue( GridWidthProperty , value );
            }
        }
 
        private static void OnGridWidthPropertyChanged( DependencyObject obj , DependencyPropertyChangedEventArgs args )
        {
            if( obj != null )
            {
                MainPage mainPage = obj as MainPage;
 
                mainPage.column1.Width = new GridLength( mainPage.GridWidth , GridUnitType.Pixel );
            }
        }
 
 
        private void btnShowHide_Click( object sender , System.Windows.RoutedEventArgs e )
        {
            btnShowHide.IsEnabled = false;
 
            Storyboard storyboard = ( this._isColumnCollapsed == true ) ? this.Resources[ "ShowColumn" ] as Storyboard : this.Resources[ "HideColumn" ] as Storyboard;
            
            storyboard.Stop();
 
            storyboard.Begin();
        }
 
        private void DoubleAnimation_Completed( object sender , EventArgs e )
        {
            this._isColumnCollapsed = !this._isColumnCollapsed;
            btnShowHide.IsEnabled = true;
 
            btnShowHide.Content = new TextBlock { Text = ( this._isColumnCollapsed == true ) ? "Show Column" : "Hide Column" };
        }
 
    }
}

 

不過,這樣做有一個很大的缺點,就是在Blend中想編輯該Storyboard的時候,Blend會認為XAML有誤,而沒辦法編輯,只能乖乖的去Key XAML了。

image

雖然不是很完美,但是這樣至少還是可以達到動畫切換Grid中Row和Column大小的效果,在研究出更好的方式前,就先將就著用吧 >"<

另外一併附上專案原始檔,請服用: