Как кнопка может нажать на UserControl выполнить метод в содержащем окне?
у меня есть UserControl, мы назовем его myUC
, Это один из нескольких UserControls в главном окне (myWindow
) моего приложения WPF. myUC
содержит ряд стандартных элементов управления, один из которых является кнопкой, мы назовем его myButton
.
когда я нажимаю myButton
, Я хотел бы выполнить myMethod()
, который существует в коде позади myWindow.
проблемой myUC
понятия не имеет, что myWindow
даже существует, гораздо меньше, чем myMethod существует.
как я могу отправить сообщение: "Эй, myWindow, проснись. myButton на myUc просто щелкнул; пожалуйста, запустите myMethod'?
6 ответов
вы можете создать команду в окне и задать для свойства команды кнопки имя этой команды. Нажатие кнопки приведет к запуску команды, без необходимости ссылки на родительское окно.
что мне на самом деле пришлось делать в 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 и добавьте два метода обработчика к привязке (это часть это совсем другое между 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
добавьте новую пользовательскую команду в объект button на UserControl. С пользовательской командой это казалось невозможным в 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.) У меня есть личная пустота в главном окне.xaml, который я хочу запустить при нажатии кнопки (btnGetSurvey) в GetSurveyByID.код XAML.
это решение одной строки работало довольно хорошо для меня.
this.ucSurveyHeader.ucGetSurveyByID.btnGetSurvey.Click += new RoutedEventHandler(btnGetSurvey_Click);
каждый элемент управления имеет родительское свойство, которое говорит вам, кто на самом деле" владеет " этим элементом управления. Вы можете использовать это вместе с литьем типа для доступа к myMethod вашего myWindow.
Вы также можете использовать отправитель аргумент вашего обработчика событий, как это:
(sender as MyWindow).myMethod()
попробуйте что-то вроде этого статический вспомогательный метод:
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);