eran otzap
eran otzap

Reputation: 12533

Trigger an EventTrigger by an AttachedEvent

I have a a custom Panel that raises a RoutedEvent which is defined globally in a static class :

 public class CompressItemsToFitStackPanel : StackPanel
 {
    protected override Size ArrangeOverride(Size arrangeSize)
    {        
        // some logic 
        // Raise Attached Event     
        CustomEventManager.RaiseArrangeEvent(this);
        return base.ArrangeOverride(arrangeSize); 
    }         
 }

My attached Event:

 public static class CustomEventManager
{                        
    public static readonly RoutedEvent ArrangeEvent = EventManager.RegisterRoutedEvent("Arrange",
                                RoutingStrategy.Bubble,
                                typeof(RoutedEventHandler),
                                typeof(CustomEventManager));

    internal static void RaiseArrangeEvent(UIElement target)
    {
        var args = new RoutedEventArgs(ArrangeEvent);
        target.RaiseEvent(args);            
    }       
} 

this Panel is the items panel for an Items control , the ItemsTemplate as an EventTrigger which i wan't to fire when the attached event is raised:

  <DataTemplate DataType="{x:Type local:Checker}" x:Key="CheckerTempalte">

    <Ellipse x:Name="ellipse" Style="{StaticResource checkerStyle}">
        <Ellipse.Triggers>
            <EventTrigger RoutedEvent="local:CustomEventManager.Arrange">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames 
                                    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" 
                                    Storyboard.TargetName="ellipse"
                                >
                            <EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
                            <EasingDoubleKeyFrame KeyTime="0:0:1" Value="{Binding Val}" />
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>                    
        </Ellipse.Triggers>        
    </Ellipse>

The Event trigger is not triggered ,

Maybe i'm not using AttachedEvents correctly or it is not Declared correctly i need the event from the panel to propagate and trigger the EventTriggers in the Child elements ,

any ideas what i'm doing wrong ?

EDIT :

After dkozl's insight i came to the conclusion that i need an AddXXXHandler and RemoveXXXHandler in order for the XAML to add/ remove the handler for the EventTrigger

    public static void AddArrangeHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie != null)
        {
            uie.AddHandler(CustomEventManager.ArrangeEvent, handler);
        }
    }

    public static void RemoveArrangeHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie != null)
        {
            uie.RemoveHandler(CustomEventManager.ArrangeEvent, handler);
        }
    } 

but still nothing happens , and i never reach these methods .

EDIT 2 :

thanks to dkozl's comments below ,

the Event is raised for each child element , since he the ellipses are down the Visual Tree .

  protected override Size ArrangeOverride(Size arrangeSize)
  {                    
      foreach (UIElement child in children)
      {                        
           CustomEventManager.RaiseArrangeEvent(child);                                            
      } 
  }

but still nothing happens , iv'e also tested the 'StoryBoard' by giving the 'EventTrigger' the 'MouseEnter' event and moving my mouse over the element , it works fine.

still , even raising the event on each Ellipse still does not work ... any ideas ?

Another point of interest is that the child elements are actually the 'Checker' type and not the Ellipse which the DataTemplate represents , i don't get how 'Checker' is considered a UIElement .?

Upvotes: 0

Views: 1021

Answers (2)

cbuteau
cbuteau

Reputation: 752

You should maybe consider a code only approach to this problem. If you wish to define the animations in XAML you can possibly StaticResource them into properties on the CompressToFitStackPanel. But if your DataTemplate is referring to a specific transform by index you are definitely losing the power and abstraction of DataTemplate'ing.

Reevaluate your problem space and what the design is supposed to solve. Use ILSpy or Reflector to analyze how other Panels solved problems with properties or Attached Dependency Properties (Grid.Column, Grid.Row).

Place more of the burden on the new layout panel and less on those who use it.

Good luck.

Upvotes: 0

dkozl
dkozl

Reputation: 33364

What you've created is standard RoutedEvent, not an attached one. Add/Remove handler is different for attached events. You'll need two separate methods (AddArrangeChildrenHandler and RemoveArrangeChildrenHandler). It has been explained on MSDN site

UPDATE: I've copied updated Ellipse definition and CustomEventManager class into my application, added test button which calls CustomEventManager.RaiseArrangeEvent(ellipse); when clicked and it works for me.

I also had to add Ellipse.RenderTransorm of TransformGroup, fourth transformation being TranslateTransform to make it work like in the example

UPDATE2: Event is raised on the panel where the Ellipse is placed which means that bubbling event would never reach it as it will start from the panel and go up the visual tree to Window never reaching children of the panel

Upvotes: 1

Related Questions