0

I've got a storyboard that I use to change the size of a Grid when a ToggleButton is pressed but the Grid's Height is hardcoded. How do I set its Height based on some other element but also add extra pixels to it? To be more specific, I want the Grid to be 50pt when collapsed but when expanded it should be 50pt+Height of another element (which will be shown in the Grid, in the extra space).

<Style TargetType="{x:Type Grid}" x:Key="ExpandCollapseTopBar">
    <Style.Triggers>
        <EventTrigger RoutedEvent="ToggleButton.Checked">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(Grid.Height)" From="50.0" To="100.0" Duration="0:0:0.1"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
        <EventTrigger RoutedEvent="ToggleButton.Unchecked">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(Grid.Height)" From="100.0" To="50.0" Duration="0:0:0.1"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Style.Triggers>
</Style>

I would use binding to the other element's Height but then I cannot add the extra pixels.

Height="{Binding ElementName=TheOtherElement, Path=ActualHeight}"
Val
  • 1,548
  • 1
  • 20
  • 36
  • You can define a converter to apply to your binding: Height="{Binding ElementName=TheOtherElement, Path=ActualHeight, Converter={StaticResource YourConverter}" Then add those 50px in the converter. – Lamelas84 Aug 31 '17 at 09:46
  • Damn, using a bind in the storyboard properties seems to crash the app – Val Aug 31 '17 at 14:03
  • Yes: https://stackoverflow.com/questions/2186933/wpf-animation-binding-to-the-to-attribute-of-storyboard-animation. That's another reason why you should apply the animations programmatically as I suggested in my answer. – mm8 Aug 31 '17 at 14:10

2 Answers2

1

You could use a library like CalcBinding which creates a binding markup extension to do this.

I haven't try it but it should work like this :

Height="{calc:Binding ElementName=TheOtherElement, Path=ActualHeight + 50}"

If you don't want to rely on an external library, the way to go is to use a Converter which would add the extra pixels. To do something as simple as this, this is the route I would follow.

Tom C.
  • 593
  • 4
  • 12
1

Apply the animations programmatically by handling the ToggleButton.Checked and ToggleButton.UnChecked events for the Grid:

private void Grid_Checked(object sender, RoutedEventArgs e)
{
    Storyboard sb = new Storyboard();
    double height = 100; //set whatever height you want here
    DoubleAnimation animation = new DoubleAnimation() { From = 50.0, To = height, Duration = TimeSpan.FromSeconds(1) };
    Storyboard.SetTargetProperty(animation, new PropertyPath("(Grid.Height)"));
    Storyboard.SetTarget(animation, sender as Grid);
    sb.Children.Add(animation);
    sb.Begin();
}

Then you can calculate the height however you want. You can't do this in a markup language such as XAML.

And this does not break the MVVM in any way whatsoever. MVVM is not about eliminating view-related code from the views. It is about separation of concerns.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • Is there no way to just add Height="{Binding ElementName=TheOtherElement, Path=ActualHeight}"? That would be a quick fix and no need to rewrite it in C#. Unfortunately, I see adding this binding in a Storyboard property seems to crash the app. Am I doing it wrong? – Val Aug 31 '17 at 14:06
  • 1
    You can generally not apply bindings in Storyboard because they are frozen for performance reasons. So no, there is no "way to just add ...". And this is certainly not a big "rewrite". – mm8 Aug 31 '17 at 14:09
  • 1
    I've decided to abandon the idea and just hardcode the storyboard values but your answer seems to be the closest to what I needed to achieve so I'm marking it as the answer. – Val Sep 01 '17 at 08:55