Подпишитесь слабо на события, полученные отражением - PullRequest
1 голос
/ 18 июля 2011

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

Я пытаюсь заставить MessageBox появляться при возникновении события,указанный в объявлении MessageBox.

Например, это будет указано в XAML окна, в котором должен появиться MessageBox.

<dialog:MessageBox
    ShowOnEvent="EventRaised"
    EventContext="{Binding}"
    Message="I am a message box"
    IconType="Warning"
    ButtonsType="YesNo" />

Способ, которым этов настоящее время работает: в MessageBox ViewModel я использую отражение, чтобы получить EventInfo для события, затем подписываюсь напрямую:

if (eventContext != null && showOnEvent != string.Empty)
{
    EventInfo eventInfo = eventContext.GetType ().GetEvent (showOnEvent);
    if (eventInfo != null)
    {
        eventInfo.AddEventHandler (eventContext, eventHandler);
    }
    else
    {
        Debug.WriteLine (string.Format ("Dialog: Couldn't find event {0} on {1}, check event name.", showOnEvent, eventContext));
    }
}

Это показывает MessageBox при возникновении события, какожидается.

Однако , обработчик события означает, что MessageBox ViewModel не GC'd, когда расположен вид главного окна.Это означает, что если создается другое представление для главного окна, создается другое MessageBox, поэтому, если событие вызывается, будут отображаться оба MessageBox s.

Я попытался обойти это с помощью WeakEventManager, но в документации Weak Event Patterns указано, что реализация WeakEventManager должна обрабатывать только одно событие - это означает, что я не могу создать ShowOnEventEventManager с именем события в качестве строкового свойства иподпишитесь на это.

У кого-нибудь есть идеи, как лучше всего это сделать?

Ответы [ 2 ]

1 голос
/ 18 июля 2011

Наличие слабого события не решит вашу проблему, потому что вы не будете отписаны до тех пор, пока GC не решит запустить (если вы явно не вызываете GC.Collect()).Как предлагает Уилл в комментариях, вы можете попытаться отписаться в соответствующее время, или, что может быть еще проще, просто проверьте свой MessageBox, если он IsLoaded, прежде чем показывать себя.

Я не буду беспокоиться о коде- в вашем MessageBox, если вы не знаете причину, по которой это повредит его повторному использованию.Хорошо, чтобы код MessageBox ссылался на его представление напрямую, если потребители MessageBox имеют дружественный к MVVM API.

0 голосов
/ 18 июля 2011

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

На соответствующей странице приведены примеры правильного кода, а также обязательные блок-схемы. Агрегатор событий довольно прост в использовании: вы Publish со строго типизированной полезной нагрузкой и Subscribe в любом количестве мест. (И это бесплатно скачать )

...