UserControl
我喜欢 Jesse 提出事件的想法:它非常类似于 WPF,并且允许需要记录内容的窗口与提供日志记录的窗口之间松散耦合。此外,进行日志记录的用户控件不依赖于实际可用的日志记录服务,这将使解决方案更加灵活。
这将如何工作
UserControl
需要记录的只是引发一个包含相关信息(要记录的文本消息)的冒泡事件。UC 将不知道如何处理或即使处理该消息,它只是提出它。这是一个轻量级的操作,并且耦合是最小的。
引发的消息在层次结构链中向上冒泡,一直到顶级元素 ( Window
, Page
)。在此过程中的任何地方,元素都可以为此事件类型提供处理程序,并通过它获得有关日志请求的通知。同样,耦合非常松散:实现的地方并不关心谁发送了消息。可以是 UserControl 或其他任何东西。
问题
如果 anUIElement
可用作日志消息事件的来源,这绝对可以正常工作。
下面是一步一步的实现:
日志服务类
我们不能为此目的重用现有事件,需要创建一个新事件(以避免混淆)。这应该这样做:
// Subclass of RoutedEventArgs that allows us to easily and nicely pass the message
// to be logged
public class LogEventArgs : RoutedEventArgs
{
public string Msg { get; set; }
public LogEventArgs(RoutedEvent routedEvent, Object sender, string Msg)
:base(routedEvent, sender)
{
this.Msg = Msg;
}
}
// This is the Delegate that's used to grab the Log message
public delegate void RoutedLogEventHandler(Object sender, RoutedEventArgs e);
// This works as the abstraction layer that will allow UC's to raise LOG messages
// and allow your implementation to alter the way it handles those LOG messages.
// Since we're doing this with a routed event, we need an DependencyObject to
// reigster it.
public class LogServices :UIElement
{
public static RoutedEvent LogEvent;
// Static constructor, registers the event
static LogServices()
{
LogEvent = EventManager.RegisterRoutedEvent("Log", RoutingStrategy.Bubble, typeof(RoutedLogEventHandler), typeof(UIElement));
}
// This helps raise the relevant shared event
public static void RaiseLog(string Msg, UIElement sender)
{
sender.RaiseEvent(new LogEventArgs(LogEvent, sender, Msg));
}
}
上面的代码声明了子类,RoutedEventArgs
因为我们需要传递我们的字符串 Message。然后它创建一个接受我们LogEventArgs
参数的新委托类型,最后从LogServices
.
如何发送事件
发送事件非常简单。这是按钮的 Click 处理程序:
LogServices.RaiseLog("Message to be logged.", sender as Button)
接收事件
我们的事件被注册为“冒泡”事件:它将从我们引发它的控件开始,并让每个父级都有机会处理它,一直到窗口。最简单的事情是在进行Window
日志记录的事件中处理事件。不幸的是,这种类型的共享不能直接从 中设置XAML
,它需要从代码中分配。这就是我尝试从 分配它的方式XAML
,但它不起作用:
<Grid local:LogService.Log="HandlerName" />
下一个选项是从代码中分配它。这是我的测试中的一个片段Window1
:
// Window Constructor
public MainWindow()
{
InitializeComponent();
// Set the event handler.
base.AddHandler(LogServices.LogEvent, new RoutedLogEventHandler(HandleMsgLog));
}
// This is the actual handler.
public void HandleMsgLog(Object sender, RoutedEventArgs e)
{
// Put the received message into the ListBox
LB.Items.Add((e as LogEventArgs).Msg);
}