Search code examples
c#wpfwinformsxamluser-controls

Call public function in Main Window from a User Control WPF


I have a Main Window which includes some User Controls that are initialized in the WPF XAML
MainWindow.xaml.

<Grid>
    <local:RegularUnit x:Name="ucRegularUnit" Grid.Row="0" />
    <local:Actions x:Name="ucActions" Grid.Row="1" />
    // .....
</Grid>

I have a public function in the Main Window which I want to call after clicking a Button in my User Control. After searching for some solutions, I found a way to get the parent window instance in my User Control class, but it can't find the function when I'm using parentWindow.myFunction().

User Control RegularUnit.cs:

public partial class RegularUnit : UserControl
{
    public RegularUnit()
    {
        InitializeComponent();
    }

    private void Button_SearchSerialNumber_Click(object sender, RoutedEventArgs e)
    {
        Window parentWindow = Window.GetWindow(this);
        //parentWindow.    //Can't find the function myFunction()
    }
}

MainWindow.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public void myFunction()
    {
        // Do Some Stuff...
    }
}

What am I doing wrong, and how can I fix it?


Solution

  • You can't call myFunction on parentWindow because it's not a member of the standard WPF Window class but of your custom MainWindow.

    What you could do is to cast the result of Window.GetWindow(this) to MainWindow, like

    MainWindow parentWindow = (MainWindow)  Window.GetWindow(this);
    parentWindow.myFunction();
    

    However this is a really bad class design because now your user control depends on being embedded in a specific window.

    What you should rather do is to add an event to the user control on which the parent control can subscribe to.

    public event EventHandler SerialNumberSearch;
    
    private void Button_SearchSerialNumber_Click(object sender, RoutedEventArgs e)
    {
        var handler = SerialNumberSearch;
        if (handler != null) handler(this, EventArgs.Empty);
    }
    

    Of course you could use a different kind of EventHandler, depending on what you need.