question

EmonHaque-1485 avatar image
0 Votes"
EmonHaque-1485 asked DaisyTian-1203 commented

How to sublass TriggerAction?

I've this RepeatButton:

 class ScrollButton : RepeatButton
 {
     string icon;
     public string Icon { get => icon; set { icon = value; setTemplate(); } }
     void setTemplate() {
         var border = new FrameworkElementFactory(typeof(Border));
         var path = new FrameworkElementFactory(typeof(Path)) { Name = "thePath" };
         path.SetValue(Path.StretchProperty, Stretch.Uniform);
         path.SetValue(Path.FillProperty, Brushes.Gray);
         path.SetValue(Path.DataProperty, Geometry.Parse(icon));
         border.SetValue(Border.BackgroundProperty, Brushes.Transparent);
         border.AppendChild(path);
         Template = new ControlTemplate(typeof(RepeatButton)) { 
             VisualTree = border,
             Triggers = {
                 new Trigger() {
                     Property = IsMouseOverProperty,
                     Value = true,
                     Setters = {
                         new Setter() {
                             Property = Path.FillProperty,
                             Value = Brushes.Blue,
                             TargetName = "thePath"
                         }
                     },
                     //EnterActions = { new Enter() },
                     //ExitActions = { new Exit() },
                 }
             }
         };
     }
 }

and if I add it in my view this way:

 var button = new ScrollButton() {
     Width = 50,
     Height = 50,
     Icon = Icons.ScrollUp
 };

the Trigger works:

93994-test.gif

I want to give it a ColorAnimation by subclassing TriggerAction class. I've tried this way:

 public class Enter : TriggerAction { }
 public class Exit : TriggerAction { }

but it gives me this error: 'TriggerAction' does not contain a constructor that takes 0 arguments. How do you subclass and add animations to it?

windows-wpf
test.gif (42.0 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

DaisyTian-1203 avatar image
1 Vote"
DaisyTian-1203 answered DaisyTian-1203 commented

You can install Microsoft.Xaml.Behaviors.Wpf in NuGet and create Enter as below:

  public class Enter : TriggerAction<DependencyObject>
     {
         public Enter()
         {
         }
    
         protected override void Invoke(object parameter)
         {
              
         }
     }

But it may be impossible to use it like EnterActions = { new Enter() }. From the Microsoft Document TriggerBase.EnterActions Property, the EnterActions gets (no sets) a collection of TriggerAction objects to apply when the trigger object becomes active. This property does not apply to the EventTrigger class.
And when I assign value to EnterActions like ExitActions = { new Exit() } , the error shows that Property or indexer 'TriggerBase.EnterActions' cannot be assgined to --- it is read only. It may be impossibe to implement with ExitActions =....

You could add BeginStoryboard to EnterActions, I provide you a workaround as below:

 void setTemplate()
         {
             var border = new FrameworkElementFactory(typeof(Border));
             var path = new FrameworkElementFactory(typeof(Path)) { Name = "thePath" };
             path.SetValue(Path.StretchProperty, Stretch.Uniform);
             path.SetValue(Path.FillProperty, Brushes.Gray);
             path.SetValue(Path.DataProperty, Geometry.Parse(icon));
             border.SetValue(Border.BackgroundProperty, Brushes.Transparent);
             border.AppendChild(path);
    
             Trigger trigger = new Trigger()
             {
                 Property = IsMouseOverProperty,
                 Value = true,
                 Setters = { new Setter() { Property = Path.FillProperty, Value = Brushes.Blue, TargetName = "thePath" } },
             };
    
             var enterAnimation = new ColorAnimation()
             {
                 From = Colors.Blue,
                 To = Colors.LightPink,
                 Duration = new TimeSpan(0,0,1),
                 AutoReverse = true
             };
    
             var exitAnimation = new ColorAnimation()
             {
                 From = Colors.LightPink,
                 To = Colors.Blue,
                 Duration = new TimeSpan(0,0,1),
                 AutoReverse=true
             };
    
             var propertyChain = new[]
             {
                Shape.FillProperty,
                SolidColorBrush.ColorProperty
             };
             var propertyPath = new PropertyPath("(0).(1)", propertyChain);
    
             Storyboard.SetTargetProperty(enterAnimation, propertyPath);
             Storyboard.SetTargetProperty(exitAnimation, propertyPath);
             Storyboard.SetTargetName(enterAnimation, "thePath");
             Storyboard.SetTargetName(exitAnimation, "thePath"); 
    
             var storyboard = new Storyboard();
    
             storyboard.Children.Add(enterAnimation);
             storyboard.Children.Add(exitAnimation);
    
             var action = new BeginStoryboard();
             action.Storyboard = storyboard;
    
             trigger.EnterActions.Add(action);
    
             Template = new ControlTemplate(typeof(RepeatButton))
             {
                 VisualTree = border,
                 Triggers =
                 {
                     trigger
                 }
             };
         }

The result like:
94591-3.gif


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



3.gif (33.6 KiB)
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

EnterActions takes System.Windows.TriggerActionCollection so if I want to add the Enter:

 class Enter : TriggerAction<DependencyObject>
 {
     public Enter() { }
     protected override void Invoke(object parameter) { }
 }

this way:

 System.Windows.TriggerActionCollection getActions() {
     var collection = new System.Windows.TriggerActionCollection();
     collection.Add(new Enter());
     return collection;
 }

it doesn't work. Could you please provide an example on how to put the TriggerAction in ControlTemplate.Triggers.EnterActions:

 Template = new ControlTemplate(typeof(RepeatButton)) {
     VisualTree = border,
     Triggers = {
         new Trigger() {
             Property = IsMouseOverProperty,
             Value = true,
             EnterActions = { /*new Enter()*/ }
         }
     }
 };

and animate color?

0 Votes 0 ·

@EmonHaque-1485
I updated my answer with a workaround for you, hope it helps you.

1 Vote 1 ·