2010-11-16 25 views
8

Tengo un UserControl, lo llamaremos myUC, que es uno entre varios UserControls en la ventana principal (myWindow) de mi aplicación WPF. myUC contiene una serie de controles estándar, uno de ellos es un botón, lo llamaremos myButton.¿Cómo puede un botón hacer clic en un UserControl ejecutar un método en la ventana que lo contiene?

Cuando hago clic en myButton, me gustaría ejecutar myMethod(), que existe en el código subyacente de myWindow.

El problema es que myUC ni siquiera tiene idea de que myWindow existe, y mucho menos que myMethod existe.

¿Cómo puedo enviar el mensaje: 'Hola, mi Ventana, despiértate. myButton on myUc acaba de hacer clic; por favor, ejecuta myMethod '?

Respuesta

8

Puede crear un comando en la ventana y establecer la propiedad Comando del botón con el nombre de este comando. Al hacer clic en el botón se disparará el comando, sin necesidad de una referencia a la ventana principal.

This tutorial explains everything very clearly.

+0

Yp, otra respuesta de 404, ¡esta vez incluso aceptada! – Rbjz

+2

Desenterré el artículo del archivo de internet "The Wayback Machine". No estoy seguro de que lo mejor fuera evitar enlaces rotos cuando el sitio web ya no existe y el contenido del artículo es demasiado para incluirlo aquí. https://web.archive.org/web/20121102095816/http://www.switchonthecode.com/tutorials/wpf-tutorial-command-bindings-and-custom-commands –

+0

el tutorial tenía demasiado para leer mi apetito Propuse dar un ejemplo de trabajo. – Rbjz

0

Cada control tiene una propiedad primaria que le dice quién es el "dueño" de este control. Puede usar eso junto con el tipo de conversión para acceder al myMethod de myWindow.
También es posible usar el emisor argumento de que su controlador de eventos como éste:

(sender as MyWindow).myMethod() 
+0

He intentado este enfoque y obtengo una NullReferenceException de System.Windows.Controls.Button. – wonea

4

Yo recomiendo aprender acerca Routed Events y Routed Commands - este es el tipo de cosas que están destinados a hacer.

+0

¿Quería vincular a "Problemas y descargas de MSDN Magazine"? Sería una gran respuesta si incluyes un pequeño ejemplo. – Rbjz

+0

@Rbjz No, parece que ese enlace se ha roto desde que lo publiqué. Veo sus comentarios sobre la respuesta aceptada y estoy de acuerdo con la frustración. Lamentablemente, siete años después, no estoy en condiciones de mejorar esta respuesta con un ejemplo. –

0

Pruebe algo como este método de ayuda estática:

public static T GetParentOfType<T>(DependencyObject currentObject) 
     where T : DependencyObject 
    { 
     // Get the parent of the object in question 
     DependencyObject parentObject = GetParentObject(currentObject); 

     if (parentObject == null) 
      return null; 

     // if the parent is the type then return 
     T parent = parentObject as T; 
     if (parent != null) 
     { 
      return parent; 
     } 
     else // if not the type, recursively continue up 
     { 
      return GetParentOfType<T>(parentObject); 
     } 
    } 
    public static DependencyObject GetParent(DependencyObject currentObject) 
    { 
     if (currentObject == null) 
      return null; 
     // Convert the object in question to a content element 
     ContentElement contentEl = currentObject as ContentElement; 

     if (contentEl != null) 
     { 
      // try dependencyobject 
      DependencyObject parent = System.Windows.ContentOperations.GetParent(contentEl); 
      if (parent != null) 
       return parent; 

      // Convert the contentEl to a FrameworkContentElement 
      FrameworkContentElement frameworkEl = contentEl as FrameworkContentElement; 
      // try frameworkcontentelement 
      if (frameworkEl != null) 
       return frameworkEl.Parent; 
      else 
       return null; 
     } 

     // couldn't get the content element, so return the parent of the visual element 
     return System.Windows.Media.VisualTreeHelper.GetParent(currentObject); 
    } 

ejecutarlo así:

StaticHelpers.GetParentOfType<Window>(this); 
5

Lo que en realidad llegó a tener que hacer en VB:

Crear una nueva clase pública para mis comandos personalizados porque era usted ndesirable tener mi clase MainWindow como público:

Public Class Commands 
    Public Shared myCmd As New RoutedCommand 
End Class 

Cree el ejecutar y métodos CanExecute que se ejecutan el código deseado. Estos dos métodos se han creado en el código MainWindow atrás:

Class MainWindow 

Private Sub myCmdCanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs) 
    e.CanExecute = True 
    e.Handled = True 
End Sub 

Private Sub myCmdExecuted(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs) 
    //Do stuff here... 
    e.Handled = True 
End Sub 

End Class 

Crear la unión en MainWindow de código subyacente de comandos y añadir los dos métodos de control de la unión (esta es la parte que es muy diferente entre C# y VB):

Class MainWindow 
Public Sub New() 
     // This call is required by the designer. 
     InitializeComponent() 
     //Add any initialization after the InitializeComponent() call. 
     //Create command bindings. 
     Dim cb As New CommandBinding(Commands.myCmd) 
     AddHandler cb.CanExecute, AddressOf myCmdCanExecute 
     AddHandler cb.Executed, AddressOf myCmdExecuted 
     Me.CommandBindings.Add(cb) 
End Sub 
End Class 

Añadir el nuevo comando personalizado al objeto botón en el control de usuario. Con un comando personalizado, esto no parecía posible en XAML, así que tuve que hacerlo en código subyacente. La clase comandos necesarios para ser públicos por lo que las órdenes eran accesibles en este control de usuario:

Public Class myUserControl 
    Public Sub New() 
    //This call is required by the designer. 
    InitializeComponent() 
    // Add any initialization after the InitializeComponent() call. 
    myButton.Command = Commands.myCmd 
    End Sub 
End Class 
3

Lo anterior es todo muy bien ... pero parece un poco complicado para mí ...

Mi problema similar: tengo una ventana (MainWindow.xaml) con un control de usuario (SurveyHeader.xaml) en ella y dentro de ese control de usuario es otro control de usuario (GetSurveyByID.xaml). Tengo un vacío privado en MainWindow.xaml que quiero ejecutar cuando se hace clic en un botón (btnGetSurvey) en GetSurveyByID.xaml.

Esta solución de una línea funcionó bastante bien para mí.

this.ucSurveyHeader.ucGetSurveyByID.btnGetSurvey.Click += new RoutedEventHandler(btnGetSurvey_Click); 
+0

Respuesta decente. Estos días estoy usando eventos enrutados en lugar de comandos para la mayoría de mis necesidades de este tipo. – Stewbob

Cuestiones relacionadas