Wpf 单击UserControl上的按钮如何在包含窗口中执行方法?

Wpf 单击UserControl上的按钮如何在包含窗口中执行方法?,wpf,vb.net,user-controls,Wpf,Vb.net,User Controls,我有一个UserControl,我们称之为myUC,它是WPF应用程序主窗口(myWindow)中几个UserControl之一myUC包含许多标准控件,其中一个是按钮,我们称之为myButton 当我单击myButton时,我想执行myMethod(),它存在于myWindow的代码隐藏中 问题是myUC根本不知道myWindow是否存在,更不用说myMethod是否存在了 我怎样才能发送信息:“嘿,我的窗户,醒醒。”。myUc上的myButton刚刚被点击;请运行myMethod“?每个控件

我有一个UserControl,我们称之为
myUC
,它是WPF应用程序主窗口(
myWindow
)中几个UserControl之一
myUC
包含许多标准控件,其中一个是按钮,我们称之为
myButton

当我单击
myButton
时,我想执行
myMethod()
,它存在于myWindow的代码隐藏中

问题是
myUC
根本不知道
myWindow
是否存在,更不用说myMethod是否存在了


我怎样才能发送信息:“嘿,我的窗户,醒醒。”。myUc上的myButton刚刚被点击;请运行myMethod“?

每个控件都有一个父属性,它告诉您谁实际“拥有”这个控件。您可以将其与类型转换一起使用,以访问myWindow的myMethod。
您还可以使用事件处理程序的sender参数,如下所示:

(sender as MyWindow).myMethod()

我建议学习和-这是他们要做的事情。

您可以在窗口中创建命令,并将按钮的command属性设置为该命令的名称。单击该按钮将触发该命令,而无需引用父窗口


尝试以下静态辅助方法:

    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);
    }
公共静态T GetParentOfType(DependencyObject currentObject) 其中T:DependencyObject { //获取相关对象的父对象 DependencyObject parentObject=GetParentObject(currentObject); if(parentObject==null) 返回null; //如果父项是类型,则返回 T parent=parentObject作为T; 如果(父项!=null) { 返回父母; } else//如果不是类型,则递归地继续向上 { 返回GetParentOfType(parentObject); } } 公共静态DependencyObject GetParent(DependencyObject currentObject) { if(currentObject==null) 返回null; //将相关对象转换为内容元素 ContentElement contentEl=currentObject作为ContentElement; if(contentEl!=null) { //尝试依赖对象 DependencyObject父对象=System.Windows.ContentOperations.GetParent(contentEl); 如果(父项!=null) 返回父母; //将contentEl转换为FrameworkContentElement FrameworkContentElement frameworkEl=contentEl作为FrameworkContentElement; //尝试frameworkcontentelement if(frameworkEl!=null) 返回frameworkEl.Parent; 其他的 返回null; } //无法获取内容元素,因此返回可视元素的父级 返回System.Windows.Media.VisualTreeHelper.GetParent(currentObject); } 这样执行:

StaticHelpers.GetParentOfType<Window>(this);
StaticHelpers.GetParentOfType(this);

我最终不得不在VB中完成的工作:

为我的自定义命令创建一个新的公共类,因为不希望将我的MainWindow类设置为公共类:

Public Class Commands
  Public Shared myCmd As New RoutedCommand
End Class
创建运行所需代码的Execute和CanExecute方法。这两个方法是在主窗口代码隐藏中创建的:

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
在MainWindow代码隐藏中创建命令绑定,并将两个处理程序方法添加到绑定中(这是C#和VB之间非常不同的部分):

将新的自定义命令添加到UserControl上的button对象。使用自定义命令,这在XAML中似乎不可能实现,所以我必须在代码隐藏中实现。Commands类需要是公共的,以便可以在此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

以上都是很好的。。。但对我来说似乎有点复杂

我的类似问题: 我有一个窗口(MainWindow.xaml),其中有一个UserControl(SurveyHeader.xaml),在该UserControl中有另一个UserControl(GetSurveyByID.xaml)。我在MainWindow.xaml中有一个私有的void,我想在GetSurveyByID.xaml中单击按钮(btnGetSurvey)时运行它

这一行的解决方案对我来说非常有效

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

不错的回答。这些天来,我使用路由事件而不是命令来满足大多数此类需求。我尝试过这种方法,并从System.Windows.Controls.Button获得了一个NullReferenceException。您的意思是链接到“MSDN杂志问题和下载”吗?如果你能举出一个小例子,这将是一个很好的答案。@Rbjz不,看起来自从我发布该链接以来,该链接已经断开了。我看到你对被接受的答案的评论,同意你的失望。不幸的是,七年过去了,我无法用一个例子来改进这个答案。我从“回程机器”互联网档案中找到了这篇文章。不确定最好的方法是在网站不复存在且文章内容太多无法包含在此处时避免断开链接。这篇教程读得有点太多了,不合我的胃口。我提议举一个有效的例子。
this.ucSurveyHeader.ucGetSurveyByID.btnGetSurvey.Click += new RoutedEventHandler(btnGetSurvey_Click);