C# 弱订阅通过反射获得的事件
我正在使用MVVM模式在WPF中创建一个C# 弱订阅通过反射获得的事件,c#,wpf,mvvm,weak-references,C#,Wpf,Mvvm,Weak References,我正在使用MVVM模式在WPF中创建一个MessageBox控件。此MessageBox将用于具有不同外观的多个应用程序,因此理想情况下,我希望代码不被代码隐藏 我试图在引发事件时显示MessageBox,该事件在MessageBox的声明中指定 例如,这将在窗口的XAML中指定,MessageBox将出现在该窗口中 <dialog:MessageBox ShowOnEvent="EventRaised" EventContext="{Binding}" Messa
MessageBox
控件。此MessageBox
将用于具有不同外观的多个应用程序,因此理想情况下,我希望代码不被代码隐藏
我试图在引发事件时显示MessageBox
,该事件在MessageBox
的声明中指定
例如,这将在窗口的XAML中指定,MessageBox
将出现在该窗口中
<dialog:MessageBox
ShowOnEvent="EventRaised"
EventContext="{Binding}"
Message="I am a message box"
IconType="Warning"
ButtonsType="YesNo" />
如预期的那样,在引发事件时显示消息框
但是,事件处理程序意味着当主窗口的视图被释放时,MessageBox
ViewModel不会被GC调用。这意味着如果为主窗口创建了另一个视图,则会创建另一个MessageBox
,因此如果引发事件,则会同时显示MessageBox
s
我试图通过使用WeakEventManager
来解决这个问题,但是指定WeakEventManager
的实现应该只处理一个事件-这意味着我不能将事件名称作为字符串属性制作一个showowneventmanager
,并使用该属性进行订阅
有没有人有什么好主意来解决这个问题?默认情况下,使用弱引用实现事件。您需要能够更改发布事件的代码,以便在应用程序中实现这一点
链接页面上有适当的代码示例以及必需的流程图。事件聚合器的使用非常简单:您可以使用强类型负载发布并在所需的任意位置订阅。(而且它是)默认情况下使用弱引用实现事件。您需要能够更改发布事件的代码,以便在应用程序中实现这一点
链接页面上有适当的代码示例以及必需的流程图。事件聚合器的使用非常简单:您可以使用强类型负载发布并在所需的任意位置订阅。(而且)有一个弱事件并不能解决您的问题,因为在GC决定运行之前您不会取消订阅(除非您显式调用GC.Collect()
)。正如威尔在评论中所建议的那样,您可以尝试在适当的时间取消订阅,或者更简单的方法是在显示自己之前让您的MessageBox检查它是否已加载
我不会担心MessageBox中的代码隐藏,除非您知道它会损害其可重用性的原因。只要MessageBox的使用者有一个MVVM友好的API,就可以让MessageBox代码直接引用其视图。有一个弱事件不会解决您的问题,因为在GC决定运行之前您不会被取消订阅(除非您显式调用GC.Collect()
)。正如威尔在评论中所建议的那样,您可以尝试在适当的时间取消订阅,或者更简单的方法是在显示自己之前让您的MessageBox检查它是否已加载
我不会担心MessageBox中的代码隐藏,除非您知道它会损害其可重用性的原因。只要MessageBox的使用者有一个MVVM友好的API,就可以让MessageBox代码直接引用其视图。该控件应该是一个覆盖控件吗,或者它会带来一个MessageBox
?@Will:这是一个覆盖-基本的MessageBox
对我的需求来说不够灵活。既然你在视图上订阅了一个事件,为什么不呢,它会告诉你何时取消订阅这两个事件?这个控件应该是一个覆盖吗,或者它会带来一个MessageBox
?@Will:这是一个覆盖层-基本的MessageBox
对于我的需求来说不够灵活。既然你在视图上订阅了一个活动,为什么不呢,它会告诉你何时取消订阅这两个活动?多亏了你和@Will,听unload
worked a treat:)多亏了你和@Will,听unload
worked a treat:)
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));
}
}