Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a button click on a UserControl execute a method in the containing Window?

I have a UserControl, we'll call it myUC, that is one among several UserControls in the main window (myWindow) of my WPF application. myUC contains a number of standard controls, one of them being a button, we'll call it myButton.

When I click myButton, I would like to execute myMethod(), which exists in the code-behind of myWindow.

The problem being that myUC doesn't have any idea that myWindow even exists, much less that myMethod exists.

How can I send the message: 'Hey, myWindow, wake up. myButton on myUc was just clicked; please run myMethod'?

like image 966
Stewbob Avatar asked Nov 16 '10 21:11

Stewbob


4 Answers

You can create a command in the window and set the Command property of the button to the name of this command. Clicking the button will fire the command, without a need for a reference to the parent window.

This tutorial explains everything very clearly.

like image 78
Alex B Avatar answered Nov 17 '22 21:11

Alex B


What I actually ended up having to do in VB:

Create a new Public Class for my custom commands because it was undesirable to have my MainWindow class as Public:

Public Class Commands
  Public Shared myCmd As New RoutedCommand
End Class

Create the Execute and CanExecute methods that run the desired code. These two methods were created in the MainWindow code behind:

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

Create the Command binding in the MainWindow code-behind and add the two handler methods to the binding (this is the part that is quite different between C# and 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

Add the new custom command to the button object on the UserControl. With a custom command, this did not seem to be possible in XAML, so I had to do it in code-behind. The Commands class needed to be Public so the commands were accessible in this UserControl:

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
like image 41
Stewbob Avatar answered Nov 17 '22 20:11

Stewbob


I recommend learning about Routed Events and Routed Commands - this is the sort of thing they're meant to do.

like image 4
Dan J Avatar answered Nov 17 '22 20:11

Dan J


The above is all well and good... but seems a bit convoluted to me...

My similar problem: I have a Window (MainWindow.xaml) with a UserControl (SurveyHeader.xaml) in it and inside that UserControl is another UserControl (GetSurveyByID.xaml). I have a private void in MainWindow.xaml that i want to run when a button (btnGetSurvey) is clicked in GetSurveyByID.xaml.

This one line solution worked quite well for me.

this.ucSurveyHeader.ucGetSurveyByID.btnGetSurvey.Click += new RoutedEventHandler(btnGetSurvey_Click);
like image 3
JRBlack Avatar answered Nov 17 '22 21:11

JRBlack