如何在UserControl上单击按钮来执行包含Window中的方法?

时间:2010-11-16 21:45:44

标签: wpf vb.net user-controls

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

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

问题在于myUC并不知道myWindow甚至存在,更不用说myMethod存在了。

我如何发送信息:'嘿,myWindow,醒来。 myUc上的myButton刚刚被点击;请运行myMethod'?

6 个答案:

答案 0 :(得分:8)

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

This tutorial explains everything very clearly.

答案 1 :(得分:5)

我实际上最终不得不在VB中做什么:

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

Public Class Commands
  Public Shared myCmd As New RoutedCommand
End Class

创建运行所需代码的Execute和CanExecute方法。这两个方法是在MainWindow代码后面创建的:

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代码隐藏中创建Command绑定,并将两个处理程序方法添加到绑定中(这是C#和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

将新的自定义命令添加到UserControl上的按钮对象。使用自定义命令,这在XAML中似乎不可能,因此我必须在代码隐藏中执行此操作。 Commands类必须是Public,因此可以在此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

答案 2 :(得分:4)

我建议您了解Routed EventsRouted Commands - 这是他们打算做的事情。

答案 3 :(得分:3)

以上一切都很好......但对我来说似乎有点令人费解......

我的类似问题:  我有一个带有UserControl(SurveyHeader.xaml)的Window(MainWindow.xaml),其中UserControl是另一个UserControl(GetSurveyByID.xaml)。我在MainWindow.xaml中有一个私有空格,我想在GetSurveyByID.xaml中单击一个按钮(btnGetSurvey)时运行。

这一行解决方案对我来说效果很好。

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

答案 4 :(得分:0)

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

(sender as MyWindow).myMethod()

答案 5 :(得分:0)

尝试类似这样的静态辅助方法:

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

执行它:

StaticHelpers.GetParentOfType<Window>(this);