从用户控件 WPF 调用主窗口中的公共函数

本文关键字:函数 窗口 用户 控件 WPF 调用 | 更新日期: 2023-09-27 18:18:01

我有一个主窗口,其中包括一些在 WPF XAML
中初始化的用户控件主窗口.xaml.

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

我在主窗口中有一个公共函数,我想在单击用户控件中的按钮后调用该函数。在搜索了一些解决方案后,我找到了一种在我的 User Control 类中获取父窗口实例的方法,但是当我使用 parentWindow.myFunction() 时它找不到该函数。

用户控制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...
    }
}

做错了什么,我该如何解决?

从用户控件 WPF 调用主窗口中的公共函数

不能在parentWindow上调用myFunction,因为它不是标准 WPF Window 类的成员,而是自定义MainWindow的成员。

你可以做的是将Window.GetWindow(this)的结果投射到MainWindow,比如

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

但是,这是一个非常糟糕的类设计,因为现在您的用户控件依赖于嵌入到特定窗口中。

您应该做的是将事件添加到父控件可以订阅的用户控件中。

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

当然,您可以使用不同类型的事件处理程序,具体取决于您的需求。

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

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

Dirk 建议的基于事件订阅的解决方案。我基于一个简单的委托来建立事件,但您可以遵循类似的模式,并将其基于适合你的方案的委托。

// 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();
        }
}