WPF Custom Controls Construction,Triggers and Events

If I understood your question correctly - the below is my explanation.

WPF event system offers 3 types of events: 1. Bubbling 2. Tunneling 3. Direct

If an event is defined (intrensically) as a bubbling event, then the event is bubbled up from the source to its container. For eg: If a Grid hosts two buttons - Rectangle1 and Rectangle2, then any click on these rectangles is bubbled up to the Grid. Tunneling is the opposite, where events tunnel from parent to the child.

There are Direct events which are very special - they are only applicable where events do not make sense to be bubbled up. For eg, in the above scenario, it doesnt make sense to bubble up the MouseOver event on either of Rectangles - because every time the mouse enters the rectangle the event is bubbled up to the Grid - which is what someone might expect.

Your Question:

Events that are consumable by the window (or container) that will use my control: those are the events I would like to expose to the outside.. how to write those?

You basically need to write a bubbling event. Below is an example from msdn to write a bubbling tap event on a Button (I have not tried it myself) Routed event example:

public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
"Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

Your Question:

Questions: Now I want to react in my XAML to IsMouseDown... how do I do that? there is no "IsMouseDown" Trigger.. further more what if I want to react to that in the code behind? and even further what if I want to change LeftTraingularIndicator "Fill" from the code behind?

BTW, you seem to have some confusion with events and triggers (because I see you use them interchangeably). Although they are related, they are not the same.

Getting back to your question - WPF allows for triggers on property changes - which is what essentially you are hooking to - IsMouseOver in this case. But what is missing is that the property is of the target of the ControlTemplate (which I dont know what it is). I am just extrapolating that the target of the ControlTemplate is a Rectangle. In which case, it does not have a "IsMouseDown" property for you to hook a property trigger. And that is the reason you cannot find it. The other option you have to write an AttachedEvent (they are very similar to AttachedProperties).. a whole another topic :(

I hope I tried my best :)


After extensive research...

1) Exposing events to the outside... Simply as if you were exposing from any other class.

public delegate void myDelegate(int someValue);  
public event myDelegate myEvent;

and somewhere in your code:

if(myEvent!=null)
  myEvent(5);

Nothing new in that part.

2) From the code behind create an instance constructor

public MyCustomControl()
{
    MouseMove += MyCustomControl_MouseMove;
}


void MyCustomControl_MouseMove(object sender, MouseEventArgs e)
{
   //now you can react to the movement of the mouse.
   //if for example I want to address an element, let's say a rectangle:

   var ele = (Rectangle)Template.FindName("myRect",this);
   ele.Fill=myNewBrush;

   // provided that we have an element named "myRect" (x:name="myRect") in
   // the generic.xaml style->Control Template-> which corresponds to that name.

}

3) Not recommended - as it belong to the scope of user-controls and not custom controls. Custom controls are the "atoms", user controls are more suitable to the purpose of combining controls.

But not impossible...

var myButton = (Button)Template.FindName("myButton",this);
myButton.OnMouseMove += ....

Just keep in mind that:

  • Anything that should be known in the code-behind must be named.

  • Your xaml should have no knowledge of what the code behind do. (except! - keep reading)

  • Parts that should be known in the code-behind must have the correct name when you design your XAML.

I truly hope this will help others who get a "wall" when trying to develop their own custom-controls.