Animating Grid Column

12 02 2011

Troubleshooting InvalidOperationException: DoubleAnimation cannot be used to animate property Width due to incompatible type.

Silverlight has great support for Animation and you might have experienced animating most of the controls on one or the other aspect. But animating ColumnDefinition.Width or RowDefinition.Height properties for Grid control is not straight forward. To achieve this one has to make a tweak.

Problem : InvalidOperationException: DoubleAnimation cannot be used to animate property Width due to incompatible type.

Reason : Width property of grid is not of type double but is of type GridLength. Further GridLength has a property called Value of type Double, but Value is ReadOnly so to change the width or height you have to create a new instance of the GridLength object and set it to the Width Property of the grid.

Solution: To achieve this we simply create a dependency property in our page and in the change event of that property we set the new instance of GridLength to width property of the grid.


<Grid x:Name="myGrid">
        <Grid.Resources>
            <Storyboard x:Name="myStoryboardC">
                <DoubleAnimation From="150" To="0" Duration="00:00:1"
                Storyboard.TargetName="myPageName"
                Storyboard.TargetProperty="ColumnWidth">
                    <DoubleAnimation.EasingFunction>
                        <CubicEase EasingMode="EaseOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
            <Storyboard x:Name="myStoryboardE">
                <DoubleAnimation From="0" To="150" Duration="00:00:1"
                Storyboard.TargetName= “myPageName"
                Storyboard.TargetProperty="ColumnWidth">
                    <DoubleAnimation.EasingFunction>
                        <CubicEase EasingMode="EaseOut"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="Column1" Width="150" MaxWidth="250" MinWidth="0">
            </ColumnDefinition>
            <ColumnDefinition Width="15" MaxWidth="15" MinWidth="15"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Rectangle x:Name="myRectangle"
     Fill="Blue" Width="200" Height="30" Grid.Column="0"/>

        <layoutToolkit:Accordion x:Name="acc" SelectionMode="ZeroOrMore" Grid.Column="0">
            <layoutToolkit:AccordionItem Header="hi">
                <StackPanel>
                    <TextBlock Text="1"/>
                    <TextBlock Text="2"/>
                    <TextBlock Text="3"/>
                </StackPanel>
            </layoutToolkit:AccordionItem>
            <layoutToolkit:AccordionItem Header="hi" Content="Task 2"/>
            <layoutToolkit:AccordionItem Header="hi" Content="Task 3"/>
        </layoutToolkit:Accordion>

        <Button x:Name="btnEC" Content="&lt;" Grid.Column="1" Click="Button_Click" />

        <data:DataGrid x:Name="dataGrid1" Margin="0" Grid.Column="2">
            <data:DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <StackPanel Background="LightBlue">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="This item has details." />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Here is some data: " />
                            <TextBlock Text="{Binding FirstName}" />
                            <TextBlock Text=" LastName" />
                            <TextBlock Text="{Binding LastName}" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </data:DataGrid.RowDetailsTemplate>
        </data:DataGrid>

    </Grid>


public partial class MainPage : UserControl
    {

        bool toogle;
        public MainPage()
        {
            InitializeComponent();
            this.Name = "myPageName";
        }

        public static readonly DependencyProperty ColumnWidthProperty = DependencyProperty.Register("ColumnWidth",
                                                                                                    typeof(double),
                                                                                                    typeof(MainPage),
                                                                                                    new PropertyMetadata
                                                                                                      (ColumnWidthChanged));
        public double ColumnWidth
        {
            get
            {
                return (double)GetValue(ColumnWidthProperty);
            }
            set
            {
                SetValue(ColumnWidthProperty, value);
            }
        }

        private static void ColumnWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var mainPage = (MainPage)d;
            mainPage.Column1.Width = new GridLength((double)e.NewValue);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (!toogle)
            {
                myStoryboardC.Begin();
                btnEC.Content = ">";
                toogle = !toogle;
            }
            else
            {
                myStoryboardE.Begin();
                btnEC.Content = "<";
                toogle = !toogle;
            }
        }
    }