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

Advertisements

Actions

Information

5 responses

24 02 2011
Marcio

Code seems nice, but I am not sure where to find the namespace for layouttoolkit:AccordionItem and also data:datagrid. So I can not use it yet.

26 02 2011
Dhaval Upadhyaya

Datagrid is the default control and if you drag the control from toolbox on silverlight page or usercontrol it will add the reference for you.

AccordionItem is not supplied with default control package so for that you will require Layout Toolkit available on codeproject. Once you install, add it to your toolbox and drag it on your page.

System.String is not used anywhere in my given snippet. If you have your own code than its fine. You have to add reference to xmlns:System=”clr-namespace:System;assembly=mscorlib” namespace in your xaml.

Hope this answers your queries.

24 02 2011
Marcio

Ok!
To compile you will need to add the two namespaces below:
xmlns:layoutToolkit=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit”
xmlns:data=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”
After that the code compiles OK. However, I am still getting an issue with system.string on code behind. I guess, I may be missing something else.

26 09 2012
burt

Sorry for not understanding but I get error: Cannot resolve TargetName myPageName. What am I doing wrong?

27 09 2012
Dhaval Upadhyaya

As shown in the code try to give Name for the page or user control you are using

public MainPage()
{
InitializeComponent();
this.Name = “myPageName”;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: