我正在使用MVVM模式在WPF中进行MessageBox
控制。这个MessageBox
将在具有不同外观的多个应用程序中使用,因此理想情况下我希望将代码保留在代码隐藏之外。
我正在尝试在MessageBox
的声明中指定引发事件时显示MessageBox
。
例如,这将在MessageBox
出现的窗口的XAML中指定。
<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
。
但是,事件处理程序意味着在放置主窗口的View时MessageBox
ViewModel不是GC'd。这意味着如果创建了主窗口的另一个视图,则会创建另一个MessageBox
,因此如果引发了该事件,则会显示MessageBox
个。{/ p>
我尝试使用WeakEventManager
解决此问题,但Weak Event Patterns documentation指定WeakEventManager
的实现只应处理一个事件 - 这意味着我无法生成{ {1}}将事件名称作为字符串属性并使用它进行订阅。
有没有人对最佳方法有任何想法?
答案 0 :(得分:1)
弱事件无法解决您的问题,因为在GC决定运行之前您不会被取消订阅(除非您明确调用GC.Collect()
)。正如Will在评论中建议的那样,你可以尝试在适当的时候取消订阅,或者更容易的是让你的MessageBox在显示之前检查它是否IsLoaded
。
我不担心你的MessageBox中的代码隐藏,除非你知道它会损害其可重用性的某些原因。只要MessageBox的使用者拥有一个MVVM友好的API,就可以让MessageBox代码直接引用它的视图。
答案 1 :(得分:0)
PRISM EventAggregator
默认使用弱引用实现事件。您需要能够更改发布事件的代码,以便在您的应用中实现此功能。
链接页面上有正确的代码示例以及强制性流程图。事件聚合器使用起来非常简单:您Publish
具有强类型有效负载,Subscribe
可以在您需要的任意位置使用。 (它是free to download)