2010-11-16 9 views
8

Mam UserControl, nazwać to myUC, który jest jednym z wielu UserControls w głównym oknie (myWindow) mojej aplikacji WPF. myUC zawiera szereg standardowych elementów sterujących, z których jednym jest przycisk, a my go nazwiemy myButton.W jaki sposób przycisk kliknięcia na UserControl może wywołać metodę w oknie zawierającym?

Po kliknięciu przycisku myButton chciałbym wykonać polecenie myMethod(), które istnieje w wersji kodującej myWindow.

Problem polegający na tym, że myUC nie ma żadnego pomysłu, że myWindow nawet istnieje, o wiele mniej niż myMethod.

Jak mogę wysłać wiadomość: "Hej, myWindow, obudź się. myButton na myUc został właśnie kliknięty; uruchom program myMethod?

Odpowiedz

8

Możesz utworzyć polecenie w oknie i ustawić właściwość Command przycisku dla nazwy tego polecenia. Kliknięcie przycisku uruchamia polecenie, bez potrzeby odwoływania się do okna nadrzędnego.

This tutorial explains everything very clearly.

+0

Yp, kolejna odpowiedź 404, tym razem nawet zaakceptowana! – Rbjz

+2

Wykopałem artykuł z internetowego archiwum "The Wayback Machine". Nie jestem pewien, czy najlepiej było unikać niedziałających linków, gdy strona już nie istnieje, a treść artykułu jest zbyt duża, by ją tu zawrzeć. https://web.archive.org/web/20121102095816/http://www.switchonthecode.com/tutorials/wpf-tutorial-command-bindings-and-custom-commands –

+0

samouczek miał trochę za dużo czytania mój apetyt. Zaproponowałem, aby dać przykład działania. – Rbjz

0

Każdy element sterujący ma właściwość nadrzędną, która informuje, kto faktycznie "posiada" tę formant. Możesz użyć tego obok funkcji rzutowania, aby uzyskać dostęp do myMindod myMethod.
Można również użyć nadawcy argument programu obsługi zdarzeń tak:

(sender as MyWindow).myMethod() 
+0

Próbowałem tego podejścia i uzyskałem wyjątek NullReferenceException z System.Windows.Controls.Button. – wonea

4

polecam poznawania Routed Events i Routed Commands - jest to rodzaj rzeczy oni oznaczało zrobić.

+0

Czy chodziło Ci o link do "MSDN Magazine Issues and Downloads"? Byłoby świetną odpowiedzią, gdybyś włączył mały przykład. – Rbjz

+0

@Rbjz Nope, wygląda na to, że ten link się zepsuł odkąd go opublikowałem. Widzę twoje komentarze na temat zaakceptowanej odpowiedzi i zgadzam się z frustracją. Niestety, po siedmiu latach, nie jestem w stanie poprawić tej odpowiedzi na przykładzie. –

0

Spróbuj coś takiego statycznej metody pomocnika:

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

wykonać ją tak:

StaticHelpers.GetParentOfType<Window>(this); 
5

What I rzeczywiście skończyło się to zrobić w VB:

Utwórz nową klasę publiczną dla moich poleceń niestandardowych, ponieważ to było u ndesirable mieć moją klasę MainWindow jak Udostępnienie:

Public Class Commands 
    Public Shared myCmd As New RoutedCommand 
End Class 

Tworzenie Execute i metody CanExecute które działają żądany kod. Te dwie metody zostały stworzone w kodzie MainWindow tyle:

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 

Tworzenie wiązania w MainWindow kodu za polecenie i dodać dwóch metod obsługi do wiązania (jest to część, która jest zupełnie inna od C# i 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 

Dodaj nowe polecenie niestandardowe do obiektu przycisku w UserControl. Dzięki komendzie niestandardowej nie było to możliwe w XAML, więc musiałem to zrobić z opóźnieniem kodu. Klasa Komendy musiała być publiczny więc polecenia były dostępne w tym 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 
3

Powyższe jest wszystko dobrze ... ale wydaje się to trochę skomplikowane do mnie ...

Mam podobny problem: Mam okno (MainWindow.xaml) z UserControl (SurveyHeader.xaml) w nim i wewnątrz tego UserControl jest kolejnym UserControl (GetSurveyByID.xaml). Mam prywatną pustkę w MainWindow.xaml, którą chcę uruchomić po kliknięciu przycisku (btnGetSurvey) w GetSurveyByID.xaml.

To jednoliniowe rozwiązanie sprawdziło się całkiem dobrze.

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

Przyzwoita odpowiedź. W dzisiejszych czasach używam Routed Events zamiast Command dla większości moich potrzeb tego typu. – Stewbob