简体   繁体   中英

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?

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.

System.Windows.Application.Current.Windows.OfType<YourWindow>().SingleOrDefault(x => x.IsActive).YourPublicMethod();

虽然上面的代码是一种凌乱的方式,但它仍然完成了工作。

Solution based on event subscription as suggested by Dirk. I have based event on a simple delegate but you can follow similar pattern and base it on a delegate that suits your scenario.

// In UserControl

    namespace TextEditor
    {
        public partial class TextEditorToolBar : UserControl
        {
            // you can use Action type delegate also
            public delegate void getDocumentKeywords(); 
            public event getDocumentKeywords getDocumentRakeKeywordsEvent;

            public TextEditorToolBar()
            {
                InitializeComponent();
            }

            // This is event handloer for the button on your user control
            private void ExtractRakeKeywords(object sender, RoutedEventArgs e)
            {
                 var handler = getDocumentRakeKeywordsEvent;

                 if (getDocumentRakeKeywordsEvent != null)
                     getDocumentRakeKeywordsEvent();
            }
        }
    }

// In MainWindow
namespace TextEditor
{
    public partial class MainWindow : Window
    {
        private DocumentKeywordsExtractor KeyWordsExtractor;
        public MainWindow()
        {
            InitializeComponent();
            KeyWordsExtractor = new DocumentKeywordsExtractor(richTextBox);

            // toolbar is the name given to UserControl in MainWindow.xaml
            toolbar.getDocumentRakeKeywordsEvent += ExtractRakeKeywords;

        }

        private void ExtractRakeKeywords()
        {
            KeyWordsExtractor.GetRakeKeywords();
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM