Во втором окне при двойном щелчке я хочу вызвать метод в моем MainWindow и отправить ему объект.

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

Итак, у меня вопрос: как мне вызвать мой метод public LoadSong(Song tempSong) в моем MainWindow при нажатии кнопки во втором окне (при условии, что я не могу вызвать метод напрямую)?

0
Doombox 25 Дек 2015 в 20:16

2 ответа

Лучший ответ

Есть много способов снять шкуру с этой кошки. Ниже два примера.

Первый подход

Простым подходом без каких-либо внешних библиотек было бы создать кастом даже в дочернем окне и подписаться на него от родителя. Также таким образом можно распространять объект.

Нажатие кнопки приведет к распространению события MyChildWindowEvent.

public class MyCommunicationObject
{
    public string Message { get; set; }
}

А потом дочернее окно:

public partial class ChildWindow : Window
{
    public event Action<MyCommunicationObject> MyChildWindowEvent;

    public ChildWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var myObject = new MyCommunicationObject();
        myObject.Message = "Hello from Child Window";
        this.MyChildWindowEvent(myObject);
    }
}

Нажатие кнопки приведет к распространению события MyChildWindowEvent.

В главном окне вы должны подписаться на событие, когда вы создаете дочерний диалог (в моем примере я делаю это при нажатии кнопки, потому что именно тогда создается окно).

Код главного окна:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var childWindow = new ChildWindow();
    childWindow.MyChildWindowEvent += ChildWindow_MyChildWindowEvent;
    childWindow.ShowDialog();
}

Второй подход

Или, как было предложено выше, используйте EventAggregator. Вы можете использовать, например, Prism. Вам нужно будет установить его с помощью диспетчера NuGet. После установки он позволяет использовать объект EventAggregator. Объект может распространять события, наследуемые от PubSubEvent, например:

public class MyEvent : PubSubEvent<MyCommunicationObject>
{

}

Главное окно и дочернее окно должны совместно использовать экземпляр EventAggregator. Затем вы должны подписаться на событие, которое распространяется вашим дочерним окном. Предполагая, что объект был создан в главном окне, ниже приведен пример того, как подписаться и обработать событие в главном окне (снова при нажатии кнопки):

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    var childWindow = new AnotherChildWindow(eventAggregator);

    eventAggregator.GetEvent<MyEvent>().Subscribe(obj =>
    {
        this.myTextBox2.Text = obj.Message;
    });

    childWindow.ShowDialog();
}

И дочернее окно должно опубликовать событие (вместе с объектом, который используется для связи):

private void Button_Click(object sender, RoutedEventArgs e)
{
    var myObject = new MyCommunicationObject();
    myObject.Message = "Hello from another child window";
    this.eventAggregator.GetEvent<MyEvent>().Publish(myObject);
}

Здесь, в дочернем окне, экземпляр EventAggregator поступает из главного окна.

0
PiotrWolkowski 26 Дек 2015 в 02:42

Вы можете использовать EventAggregator или другой шаблоны на основе событий.

Сначала создайте новое событие со свойством вашего типа объекта, чтобы отправлять его между компонентами.

Затем подпишитесь на MainWindow на ваше событие и вызовите LoadSong в обработчике событий с параметром, полученным из параметра обработчика.

Наконец, поднимите (или опубликуйте) ваше событие из второго окна в обработчике событий двойного щелчка.

Как видите, обе реализации являются частью библиотек MVVM и этот шаблон может быть полезен для вашего приложения.

0
Vadim Martynov 25 Дек 2015 в 17:30