UserControl
イベントを発生させるという Jesse のアイデアが気に入っています。これは非常に WPF 風であり、ログを記録する必要がある とログを提供するウィンドウとの間の疎結合を可能にします。さらに、ロギングを行う UserControls は、実際に使用可能なロギング サービスに依存しないため、ソリューションがさらに柔軟になります。
これがどのように機能するか
ログが必要なはUserControl
、関連情報 (ログに記録されるテキスト メッセージ) を含むバブリング イベントを発生させるだけです。UC は、そのメッセージがどのように処理されるか、または処理されるかどうかさえわかりません。単にそれを発生させます。それは軽量操作であり、カップリングは最小限です。
Window
発生したメッセージは、最上位の要素 ( 、 )まで階層チェーンを上っていきますPage
。途中のどこでも、要素がこのイベント タイプのハンドラーを提供し、それを介してログ リクエストについて通知を受けることができます。繰り返しますが、結合は非常に緩いです。実装が行われる場所は、誰がメッセージを送信したかを気にしません。UserControl またはその他のものである可能性があります。
問題
UIElement
ロギング メッセージ イベントの発信元として を使用できる場合、これは問題なく機能します。
ステップバイステップの実装は次のとおりです。
LogServices クラス
この目的で既存のイベントを再利用することはできません。新しいイベントを作成する必要があります (混乱を避けるため)。これはそれを行う必要があります:
// 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);
}