Compartir a través de


Cómo: Agregar control de clases a un evento enrutado

Los eventos enrutados se pueden controlar mediante controladores de clase o controladores de instancia en cualquier nodo de la ruta. Los controladores de clase se invocan primero, y las implementaciones de clase pueden usarlos para suprimir eventos del control de instancias o para introducir otros comportamientos específicos de eventos en eventos que pertenecen a clases base. En este ejemplo se muestran dos técnicas estrechamente relacionadas para implementar controladores de clase.

Ejemplo

En este ejemplo se usa una clase personalizada basada en el panel Canvas. La premisa básica de la aplicación es que la clase personalizada introduce comportamientos en sus elementos secundarios (incluido interceptar los clics del botón izquierdo del mouse y marcarlos como controlados) antes de invocar a la clase de elemento secundario o a cualquier controlador de instancia.

La clase UIElement expone un método virtual que permite el control de clases en el evento PreviewMouseLeftButtonDown, simplemente invalidando el evento. Esta es la forma más sencilla de implementar el control de clases si este método virtual está disponible en algún lugar de la jerarquía de la clase. En el código siguiente se muestra la implementación OnPreviewMouseLeftButtonDown en "MyEditContainer" que se deriva de Canvas. La implementación marca el evento como controlado en los argumentos y, después, agrega código para proporcionar al elemento de origen un cambio visible básico.

protected override void OnPreviewMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
    e.Handled = true; //suppress the click event and other leftmousebuttondown responders
    MyEditContainer ec = (MyEditContainer)e.Source;
    if (ec.EditState)
    { ec.EditState = false; }
    else
    { ec.EditState = true; }
    base.OnPreviewMouseRightButtonDown(e);
}
Protected Overrides Sub OnPreviewMouseRightButtonDown(ByVal e As System.Windows.Input.MouseButtonEventArgs)
    e.Handled = True 'suppress the click event and other leftmousebuttondown responders
    Dim ec As MyEditContainer = CType(e.Source, MyEditContainer)
    If ec.EditState Then
        ec.EditState = False
    Else
        ec.EditState = True
    End If
    MyBase.OnPreviewMouseRightButtonDown(e)
End Sub

Si no hay ningún virtual disponible en las clases base o para ese método en concreto, el control de clases se puede agregar directamente mediante un método de utilidad de la clase EventManager, RegisterClassHandler. Solo se debe llamar a este método dentro de la inicialización estática de las clases que agregan control de clases. En este ejemplo se agrega otro controlador para PreviewMouseLeftButtonDown y, en este caso, la clase registrada es la clase personalizada. En cambio, cuando se usan virtuales, la clase registrada es realmente la clase base UIElement. En los casos en los que tanto las clases base como la subclase registren el control de clases, primero se invocará a los controladores de la subclase. El comportamiento en una aplicación sería, en primer lugar, que este controlador mostraría su cuadro de mensaje y, después, se mostraría el cambio visual en el controlador del método virtual.

static MyEditContainer()
{
  EventManager.RegisterClassHandler(typeof(MyEditContainer), PreviewMouseRightButtonDownEvent, new RoutedEventHandler(LocalOnMouseRightButtonDown));
}
internal static void LocalOnMouseRightButtonDown(object sender, RoutedEventArgs e)
{
  MessageBox.Show("this is invoked before the On* class handler on UIElement");
  //e.Handled = true; //uncommenting this would cause ONLY the subclass' class handler to respond
}
Shared Sub New()
    EventManager.RegisterClassHandler(GetType(MyEditContainer), PreviewMouseRightButtonDownEvent, New RoutedEventHandler(AddressOf LocalOnMouseRightButtonDown))
End Sub
Friend Shared Sub LocalOnMouseRightButtonDown(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("this is invoked before the On* class handler on UIElement")
    'e.Handled = True //uncommenting this would cause ONLY the subclass' class handler to respond
End Sub

Vea también