none
ControlTemplate: Binding Width of a Button during animation to the actual Button's Width RRS feed

  • Question

  • Hello,

    i have created a custom Button, with its own look and feel. When the button is clicked i wish to change its animation, which all works fine.  However during the animation rather than having fixed low values for Width and height of the button (in this case 50 for height), I wish to obtain the original set Width and height of the Button set by user and divide it by 3.  I think a converter could help, but I get a different error message:

    Cannot convert the value in attribute 'To' to object of type ''.  Error at object 'System.Windows.Media.Animation.DoubleAnimation' in markup file

    It seems TemplateBinding doesnt find a value inside my Button --> Width, however my Button inside the GRID has a Width property set...I dont get it.  Once this works I assume, I could use a converter to divide the Width by 3. How do I get that far? Any idea?

    Thanks


    <ControlTemplate x:Key="ButtonTemplate" TargetType="Button"
                <Grid> 
                    <Ellipse Name="Ellipse1" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
                        <Ellipse.Fill> 
                            <RadialGradientBrush GradientOrigin=".5,.5"
                                <GradientStop Color="Red" Offset="0"/> 
                                <GradientStop Color="Orange" Offset="0.25"/> 
                                <GradientStop Color="Blue" Offset="0.5"/> 
                                <GradientStop Color="Yellow" Offset="0.75"/> 
                                <GradientStop Color="Green" Offset="1"/> 
                            </RadialGradientBrush> 
                        </Ellipse.Fill> 
                    </Ellipse> 
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> 
                </Grid> 
                <ControlTemplate.Triggers>                 
                    <EventTrigger RoutedEvent="Button.Click"
                        <BeginStoryboard> 
                            <Storyboard AutoReverse="True"
                                <DoubleAnimation To="{TemplateBinding Width}" Duration="0:0:0.1" Storyboard.TargetProperty="Width"/> 
                                <DoubleAnimation To="50" Duration="0:0:0.1" Storyboard.TargetProperty="Height" /> 
                            </Storyboard> 
                        </BeginStoryboard> 
                    </EventTrigger> 
                </ControlTemplate.Triggers>             
            </ControlTemplate> 

    Sunday, February 22, 2009 1:27 PM

Answers

  • Code behind is a must to have a button animated when clicked to shrink to 1/3rd of the original size of the button.
    Below is a workaround I build this morning.
    In this simple project, DoubleAnimation, Storyboard, BeginStoryboard and EventTrigger were created in memory.
    In the Window loaded event, the ControlTemplate of Button is achieved directly. One instance of EventTrigger was added into the Button's Triggers.
    For example:
    XAML:
    <Window x:Class="_temple.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            xmlns:local="clr-namespace:_temple" 
         Loaded="Window_Loaded" 
            Name="w1" 
        Title="Window1" Height="500" Width="500"
        <Grid> 
            <Button Name="btn"   Width="300" Height="300"  >  
                <Button.Style> 
                    <Style x:Name="aa"  TargetType="Button"
                        <Setter  Property="Template"
                            <Setter.Value> 
                                <ControlTemplate TargetType="Button"
                                    <Grid  > 
                                        <Ellipse Name="Ellipse1" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
                                            <Ellipse.Fill> 
                                                <RadialGradientBrush GradientOrigin=".5,.5"
                                                    <GradientStop Color="Red" Offset="0"/> 
                                                    <GradientStop Color="Orange" Offset="0.25"/> 
                                                    <GradientStop Color="Blue" Offset="0.5"/> 
                                                    <GradientStop Color="Yellow" Offset="0.75"/> 
                                                    <GradientStop Color="Green" Offset="1"/> 
                                                </RadialGradientBrush> 
                                            </Ellipse.Fill> 
                                        </Ellipse> 
                                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> 
                                    </Grid> 
                                </ControlTemplate> 
                            </Setter.Value> 
                        </Setter> 
                    </Style> 
                </Button.Style>  
            </Button> 
        </Grid> 
    </Window> 
     

    C#:
    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Media.Animation; 
    namespace _temple 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public Window1() 
            { 
                InitializeComponent(); 
            } 
            private void Window_Loaded(object sender, RoutedEventArgs e) 
            { 
                NameScope.SetNameScope(w1, new NameScope()); 
                w1.RegisterName(btn.Name, btn); 
                DoubleAnimation daW = new DoubleAnimation(btn.Width / 3, new Duration(new TimeSpan(0, 0, 1))); 
                DoubleAnimation daH = new DoubleAnimation(btn.Width / 3, new Duration(new TimeSpan(0, 0, 1))); 
                Storyboard sb = new Storyboard(); 
                sb.Children.Add(daW); 
                sb.Children.Add(daH); 
                Storyboard.SetTargetName(daW, btn.Name); 
                Storyboard.SetTargetName(daH, btn.Name); 
                Storyboard.SetTargetProperty(daW, new PropertyPath(Button.WidthProperty)); 
                Storyboard.SetTargetProperty(daH, new PropertyPath(Button.HeightProperty)); 
                BeginStoryboard bs = new BeginStoryboard(); 
                bs.Storyboard = sb
                Style style = btn.Style; 
                Setter s = style.Setters[0] as Setter; 
                ControlTemplate ct = s.Value as ControlTemplate; 
                EventTrigger ee = new EventTrigger(); 
                ee.RoutedEvent = Button.ClickEvent; 
                ee.Actions.Add(bs); 
                btn.Triggers.Add(ee); 
            } 
        } 
     

    • Marked as answer by Tao Liang Wednesday, March 4, 2009 2:23 AM
    Wednesday, March 4, 2009 2:23 AM

All replies

  • TemplateBinding is a lightweight "binding", it doesn't support some features of traditional Binding, such as automatically type conversion using the known type converters associated with the target property .
    • Marked as answer by Tao Liang Monday, March 2, 2009 9:49 AM
    • Unmarked as answer by Kave Tuesday, March 3, 2009 7:33 PM
    Monday, March 2, 2009 9:49 AM
  • I see. But would I ever be able to have a button animated to shrink to 1/3rd of the original size of the button?

    Thanks

    Monday, March 2, 2009 10:26 AM
  • Unfortunately this didn't solve the problem yet since the question still remains how I would be able to have a button animated when clicked to shrink to 1/3rd of the original size of the button? Unless my approach using TargetProperty is completely wrong, but how else should I do that?

    hence I have removed the "marked as Answer".

    Thanks

    Tuesday, March 3, 2009 7:36 PM
  • Code behind is a must to have a button animated when clicked to shrink to 1/3rd of the original size of the button.
    Below is a workaround I build this morning.
    In this simple project, DoubleAnimation, Storyboard, BeginStoryboard and EventTrigger were created in memory.
    In the Window loaded event, the ControlTemplate of Button is achieved directly. One instance of EventTrigger was added into the Button's Triggers.
    For example:
    XAML:
    <Window x:Class="_temple.Window1" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
            xmlns:local="clr-namespace:_temple" 
         Loaded="Window_Loaded" 
            Name="w1" 
        Title="Window1" Height="500" Width="500"
        <Grid> 
            <Button Name="btn"   Width="300" Height="300"  >  
                <Button.Style> 
                    <Style x:Name="aa"  TargetType="Button"
                        <Setter  Property="Template"
                            <Setter.Value> 
                                <ControlTemplate TargetType="Button"
                                    <Grid  > 
                                        <Ellipse Name="Ellipse1" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
                                            <Ellipse.Fill> 
                                                <RadialGradientBrush GradientOrigin=".5,.5"
                                                    <GradientStop Color="Red" Offset="0"/> 
                                                    <GradientStop Color="Orange" Offset="0.25"/> 
                                                    <GradientStop Color="Blue" Offset="0.5"/> 
                                                    <GradientStop Color="Yellow" Offset="0.75"/> 
                                                    <GradientStop Color="Green" Offset="1"/> 
                                                </RadialGradientBrush> 
                                            </Ellipse.Fill> 
                                        </Ellipse> 
                                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> 
                                    </Grid> 
                                </ControlTemplate> 
                            </Setter.Value> 
                        </Setter> 
                    </Style> 
                </Button.Style>  
            </Button> 
        </Grid> 
    </Window> 
     

    C#:
    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    using System.Windows.Media.Animation; 
    namespace _temple 
        /// <summary> 
        /// Interaction logic for Window1.xaml 
        /// </summary> 
        public partial class Window1 : Window 
        { 
            public Window1() 
            { 
                InitializeComponent(); 
            } 
            private void Window_Loaded(object sender, RoutedEventArgs e) 
            { 
                NameScope.SetNameScope(w1, new NameScope()); 
                w1.RegisterName(btn.Name, btn); 
                DoubleAnimation daW = new DoubleAnimation(btn.Width / 3, new Duration(new TimeSpan(0, 0, 1))); 
                DoubleAnimation daH = new DoubleAnimation(btn.Width / 3, new Duration(new TimeSpan(0, 0, 1))); 
                Storyboard sb = new Storyboard(); 
                sb.Children.Add(daW); 
                sb.Children.Add(daH); 
                Storyboard.SetTargetName(daW, btn.Name); 
                Storyboard.SetTargetName(daH, btn.Name); 
                Storyboard.SetTargetProperty(daW, new PropertyPath(Button.WidthProperty)); 
                Storyboard.SetTargetProperty(daH, new PropertyPath(Button.HeightProperty)); 
                BeginStoryboard bs = new BeginStoryboard(); 
                bs.Storyboard = sb
                Style style = btn.Style; 
                Setter s = style.Setters[0] as Setter; 
                ControlTemplate ct = s.Value as ControlTemplate; 
                EventTrigger ee = new EventTrigger(); 
                ee.RoutedEvent = Button.ClickEvent; 
                ee.Actions.Add(bs); 
                btn.Triggers.Add(ee); 
            } 
        } 
     

    • Marked as answer by Tao Liang Wednesday, March 4, 2009 2:23 AM
    Wednesday, March 4, 2009 2:23 AM