構造
更新をかなり定期的にチェックするタイマーを起動する単純なフォームがあります。ロード時に開始するフォームのコンストラクターは次のようになります。
public MainWindow()
{
InitializeComponent();
otherWindow = new TheOtherWindow();
if (Meta.hasUpdate)
{
updateImage.Source = new BitmapImage(new Uri("/MyProject;component/Images/updateTrue.gif", UriKind.Relative));
}
Thread updateMonitor = new Thread(() =>
{
UpdateManager updater = new UpdateManager();
updater.StartUpdateMonitor();
});
updateMonitor.IsBackground = true;
updateMonitor.Start();
}
Metaクラスには、いくつかの非常に基本的な情報が含まれており、いくつかの場所で参照されているが、更新されることもあるさまざまな文字列が格納されています。その構造の中にはこれがあります:
class Meta
{
...
private static bool hasUpdate = false;
public static bool GetHasUpdate()
{
return hasUpdate;
}
public static void SetHasUpdate(bool value)
{
hasUpdate = value;
}
}
もう1つはUpdateManagerクラスです。これには、5分ごとに更新をチェックするための小さなルーチンが含まれています。
class UpdateManager
{
Timer timer;
public void CheckForUpdates(Object source, ElapsedEventArgs e)
{
if (!isUpToDate())
{
timer.Stop();
Meta.SetHasUpdate(true);
Application.Current.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show("A new update is now available!);
}));
}
}
public void StartUpdateMonitor()
{
float updateInterval = 300000;
timer = new Timer(updateInterval); // Milliseconds between checks.
timer.Elapsed += CheckForUpdates;
timer.AutoReset = true;
timer.Enabled = true;
}
}
問題
つまり、Meta.SetHasUpdate()に到達するたびにイベントを発生させ、小さなアイコンを変更して更新が利用可能であることを示すことを目的として、これをアプリケーション内のすべてのフォームにブロードキャストします。
私の試みは、INotifyPropertyChangedの実装が静的メンバーではうまく機能しないことを知って終了しました。これはそれを実装するための私の試みでした...
class Meta : INotifyPropertyChanged
{
...
private static bool hasUpdate = true;
public static bool GetHasUpdate()
{
return hasUpdate;
}
public static void SetHasUpdate(bool value)
{
hasUpdate = value;
NotifyPropertyChanged();
}
private static void NotifyPropertyChanged()
{
if (PropertyChanged != null)
{
PropertyChanged(null, new PropertyChangedEventArgs("hasUpdate"));
}
}
}
これらのメンバーは複数のフォームから読み戻す必要があるため、オブジェクトをたくさん回さずに静的にしないことはできません。これはやりたくないことです。
この場合、複数のフォームがMetaクラスから受信できるイベントをどのように発生させますか?別の構造を検討する必要がありますか、それともINotifyPropertyChangedを誤解していますか?
これを解決する方法はたくさんありますが(メタクラスのDIを各ページのViewModelに入れて、INPCに反応することを考えてください。シングルトンアプローチよりも優先されます)、考慮すべき1つのアプローチは、イベントではなくメッセージングを使用することです。メッセージ(ほとんどのMVVMフレームワークで提供されます)は、緩く結合されたコンポーネント間で通信するための優れた方法です。MVVM LightのようなMVVMライブラリを活用する場合、Messengerの実装が含まれているため、これは非常に簡単です。このアプローチの主な利点は、イベントベースのアプローチの場合のように、通知を受け取りたいフォームが必ずしもソースの参照を保持する必要がないことです。
関心のあるすべてのフォームにメッセージを登録してもらい、受信時にそれに応じて対応するだけです。
たとえば、MVVM Lightを使用すると、INPCプロパティが更新されたときにメッセージを自動的にブロードキャストすることを利用できます。
private bool hasUpdate;
public bool HasUpdate
{
{
return hasUpdate;
}
set
{
// the last bool param indicates whether or not to broadcast a message to all interested parties.
Set(nameof(HasUpdate), ref hasUpdate, value, true);
}
}
次に、アプリの完全に別個の/無関係な部分(通常はViewModel)で、このような更新に関心があることを示すためにこれを行うことができます。
Messenger.Default.Register<PropertyChangedMessage<bool>>(this, m => ReceiveHasUpdatedMessage(m));
次に、受信ラムダで:
private void ReceiveHasUpdatedMessage(PropertyChangedMessage<bool> m)
{
// react accordingly.
}
これはMessenger
、MVVMLightが提供する単純な使用例の1つにすぎません。ほとんど何でもできます。ここでの前提は、このアプローチを使用することで、利害関係者がエミッターへのハードリファレンスを必要としないようにすることです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加