0

この質問は、私が尋ねた別の質問と似ていますが、その場合はバインディングを XAML またはビュー モデルから強制的に更新することについて知りたいのですが、この場合はこれをカスタム WPF にラップすることについて知りたいFrameworkElementです。

私が求めている機能は、何かが起こってからどれくらい経ったかを示す一連のテキストです。

<TextBlock Text="It happened " />
<my:AgeTextBlock SinceTime="{Binding OccurredAtUtc}" />
<TextBlock Text=" ago" />

これは次のようにレンダリングされます (例):

1 分 13 秒前に発生しました

TimeSpanaから人が読める形式に変換するコードがあります。

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イベント ハンドラーをオーバーライドして削除する方法はありません。

ここで推奨されるパターンは何ですか?

4

2 に答える 2

4

コントロールのLoadedイベントでTickイベントをサブスクライブし、Unloadedイベントでサブスクライブを解除してみませんか?

于 2009-06-16T12:12:49.477 に答える
2

TextBlock が IDisposable を実装していないからといって、インターフェイス要件と実装を自分で追加できないわけではありません。自分自身を破棄して (ベースから何もオーバーライドしないで) 実装し、そこでタイマーを破棄することができます。

明らかに、AgeTextBlock クラスを破棄する責任があります。たとえば、ウィンドウを閉じるイベントなどでこれを行うことができます。

(または、 MVVM パターンに従い、タイマーをビュー モデルに配置する場合は、ビュー モデルを IDisposable にして、ビューをビュー モデルのタイマー値にバインドするだけです。)

[編集: ええ、これについて考えてみると、Winforms とは異なり、これをカスタム コントロールにする必要はないと思います。WPF にはカスタム コントロールが必要ありません。代わりに、ビュー モデルでタイマー プロパティを公開すると思います (おそらく事前にフォーマットされたプロパティであるため、読みやすい文字列が得られます)、そのプロパティを通常のテキスト ボックスにバインドします (カスタム コントロールはありません)。その後、スタイルまたはテンプレートを使用して、テキスト ボックスの視覚的なプロパティを微調整し、希望どおりに表示します。 . それはどのように聞こえますか?]

于 2009-06-16T11:46:50.013 に答える