毎秒更新するWPFコントロールを作成する方法は?
-
05-07-2019 - |
質問
この質問は私が尋ねた別の質問に似ていますが、その場合は、強制的にXAMLまたはビューモデルから更新します。この場合、これをカスタムWPF FrameworkElement
にラップすることについて知りたいです。
私が望んでいる機能は、何か前に起こったことを示す一連のテキストです。
<TextBlock Text="It happened " />
<my:AgeTextBlock SinceTime="{Binding OccurredAtUtc}" />
<TextBlock Text=" ago" />
これは次のように表示されます(例):
1分13秒前に発生しました
TimeSpan
から人間が判読できる形式に変換するコードがあります。
UIを毎秒更新するために、静的な DispatcherTimer
( Kent Boogaartの回答)。
だからここに私が持っているものがあります:
public class AgeTextBlock : TextBlock
{
private static readonly DispatcherTimer _timer;
static AgeTextBlock()
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
}
public AgeTextBlock()
{
_timer.Tick += ...;
}
// How can I unsubscribe from the Tick event to avoid a memory leak?
}
コメントは私の問題を示しています。このアプローチで適切にクリーンアップする方法がわかりません。イベントハンドラをオーバーライドおよび削除する Dispose
メソッドはありません。
ここで推奨されるパターンは何ですか?
解決
コントロールのLoadedイベントでTickイベントをサブスクライブせず、Unloadedイベントでサブスクライブを解除する理由
他のヒント
TextBlockがIDisposableを実装していないからといって、インターフェイス要件と実装を自分で追加できないわけではありません。破棄を実装して(ベースから何も上書きしない)、そこにタイマーを破棄できます。
AgeTextBlockクラスを破棄するのは当然のことです。たとえば、ウィンドウを閉じるイベントなどでこれを行うことができます。
(または、 MVVMパターンに従ってタイマーを設定した場合ビューモデルでは、ビューモデルをIDisposableにして、ビューをビューモデルのタイマー値にバインドするだけです。)
[編集:ええ、これについて考えると、これはWinformsとは違ってカスタムコントロールにすべきだとは本当に思っていません。WPFにはカスタムコントロールが必要ないので、代わりにタイマープロパティを公開すると思いますモデルを表示し(おそらく事前にフォーマットされたプロパティなので読みやすい文字列になります)、そのプロパティを通常のテキストボックスにバインドします-カスタムコントロールなし-次に、スタイルまたはテンプレートを使用して、テキストボックスの視覚的プロパティを調整しますどうしたか。どのように聞こえますか?]