4

My ultimate goal is to animate the change in size between two UserControls. The way that I have attempted to achieve this has produced one major problem.

I start with a DataTemplate that contains some basic text and icon display, an 'edit' UserControl with a height set to 0 and an edit button. The edit UserControl is in a GridRow with Height="Auto", so it also starts out with a height of 0. The button has a DoubleAnimation triggered by the button click that animates the height of the UserControl from 0 to 300. This all works just fine. Here is a simplified code example.

<DataTemplate x:Key="UserTemplate" DataType="{x:Type dataTypes:User}">
...
<controls:UserView Grid.Row="1" Grid.ColumnSpan="5" x:Name="EditRow" 
    DataContext="{Binding}" Height="0" />
<controls:UserEditor Grid.Row="2" Grid.ColumnSpan="5" x:Name="EditRow" 
    DataContext="{Binding}" Height="0" />
<Button Grid.Row="0" Grid.Column="4" Name="Edit" Style="{StaticResource ButtonStyle}" 
    ToolTip="Edit user" Click="Button_Click">
    <Image Source="/SolutionName;component/Images/Edit.png" Stretch="None" />
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Name="EditRowHeightAnimation" 
    Storyboard.TargetName="EditRow" Storyboard.TargetProperty="Height" From="0" 
    To="300" Duration="00:00:0.5" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>
...
</DataTemplate>

The problem is that the edit UserControl is not 300 pixels high and I won't know what height it will be at design time. I tried the following, but it doesn't work.

<DoubleAnimation Name="EditRowHeightAnimation" Storyboard.TargetName="EditRow"
    Storyboard.TargetProperty="Height" From="0" To="{Binding DesiredSize.Height, 
    ElementName=EditRow}" Duration="00:00:0.5" />

I have also tried calling Measure() and UpdateLayout() on the edit UserControl from code behind. I commented out the button click trigger and xaml animation and added one from code behind instead... now this kind of worked, but I always got the same (wrong) DesiredSize. That is, the UserControl height would get animated, but just to the wrong height. Here is the button click handler code.

private void Button_Click(object sender, RoutedEventArgs e)
{
    User currentUser = (User)CollectionViewSource.GetDefaultView(Users).CurrentItem;
    ListBoxItem listBoxItem = (ListBoxItem)
        (UsersListBox.ItemContainerGenerator.ContainerFromItem(currentUser));
    DataTemplate itemDataTemplate = FindResource("UserTemplate") as DataTemplate;
    ContentPresenter contentPresenter = listBoxItem.GetInternal<ContentPresenter>();
    if (itemDataTemplate != null && contentPresenter != null)
    {
        UserEditor userEditor = (UserEditor)itemDataTemplate.FindName("EditRow", 
            contentPresenter);
        userEditor.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        userEditor.UpdateLayout();
        userEditor.BeginAnimation(HeightProperty, new DoubleAnimation(0, 
            userEditor.DesiredSize.Height, new Duration(new TimeSpan(0, 0, 1)), 
            FillBehavior.HoldEnd), HandoffBehavior.Compose);
    }
}

So my question is how can I get the size that a UserControl would be if its container placed no size restriction upon it, when its current height is 0?

I'd also be happy to hear if there is a better way to achieve my ultimate goal. Many thanks in advance.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • I fixed a similiar problem by calling UpdateLayout on the parent of the UserControl that you want the desired height of...I also was stuck in calling Measure on the UserControl itself. UpdateLayoput of the parent will measure and arrange all child controls and gave me the Desired Height exactly, keep margins / padding in mind ;) – Youp Bernoulli Jan 08 '13 at 15:32

2 Answers2

7

You can put the content you want the size of into a Canvas with ClipToBound="True". Then you can manipulate the size of the Canvas and yet the size of the content inside the Canvas will always be its full desired size.

Rick Sladkey
  • 33,988
  • 6
  • 71
  • 95
  • Hey Rick, I believe you've helped me out before... I can't thank you enough! I've been stuck on this for ages and just knew there would be a simple solution! Thanks again. For anyone following this, using a canvas as suggested enabled me to bind the `DoubleAnimation.To` property to the `ActualHeight` property of my `UserControl`. Now it correctly slides open to whatever the required size is. – Sheridan Feb 18 '11 at 21:17
  • Dealing with a very similiar problem :( Where do you use the canvas? In XAML or in code-behind? – Youp Bernoulli Jan 08 '13 at 15:02
3

Maybe it's easier to animate the LayoutTransform.ScaleY of your target from 0 to 1, because desired height is always 1 and no extra control is needed.

Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
LPL
  • 16,827
  • 6
  • 51
  • 95