Как нажатие кнопки на UserControl может выполнить метод в содержащем окне? - PullRequest
8 голосов
/ 17 ноября 2010

У меня есть UserControl, назовем его myUC, то есть один из нескольких пользовательских элементов управления в главном окне (myWindow) моего приложения WPF.myUC содержит ряд стандартных элементов управления, один из которых является кнопкой, мы назовем ее myButton.

Когда я нажимаю myButton, я хочу выполнить myMethod(), который существуетв коде позади myWindow.

Проблема в том, что myUC даже не подозревает, что myWindow даже существует, тем более, что myMethod существует.

Как я могу отправитьсообщение: «Эй, мое окно, проснись.myButton на myUc просто нажали;пожалуйста, запустите myMethod '?

Ответы [ 6 ]

8 голосов
/ 17 ноября 2010

Вы можете создать команду в окне и установить для свойства команды кнопки имя этой команды.Нажатие на кнопку запустит команду без необходимости ссылки на родительское окно.

В этом руководстве все объясняется очень четко.

5 голосов
/ 17 ноября 2010

Что мне действительно пришлось сделать в 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

Создайте привязку Command в выделенном коде MainWindow и добавьте два метода-обработчика в привязку (это та часть, которая сильно отличается в 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 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
4 голосов
/ 17 ноября 2010

Я рекомендую узнать о маршрутизируемых событиях и маршрутизируемых командах - это то, для чего они предназначены.

3 голосов
/ 02 июня 2011

Все вышеперечисленное хорошо, но мне кажется, что оно немного запутанное ...

Моя похожая проблема: У меня есть окно (MainWindow.xaml) с UserControl (SurveyHeader.xaml) в нем, а внутри этого UserControl еще один UserControl (GetSurveyByID.xaml). У меня есть частный пробел в MainWindow.xaml, который я хочу запустить при нажатии кнопки (btnGetSurvey) в GetSurveyByID.xaml.

Это однолинейное решение хорошо сработало для меня.

this.ucSurveyHeader.ucGetSurveyByID.btnGetSurvey.Click += new RoutedEventHandler(btnGetSurvey_Click);
0 голосов
/ 17 ноября 2010

Попробуйте что-то вроде статического вспомогательного метода:

    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);
0 голосов
/ 17 ноября 2010

Каждый элемент управления имеет родительское свойство, которое сообщает вам, кто на самом деле «владеет» этим элементом управления. Вы можете использовать это вместе с приведением типа для доступа к myMethod в myWindow.
Вы также можете использовать аргумент sender вашего обработчика событий, например:

(sender as MyWindow).myMethod()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...