如何使WPF控件每秒更新一次?

时间:2009-06-16 11:39:08

标签: .net wpf multithreading timer dispatcher

这个问题类似于another one I asked,但在这种情况下,我想知道强制绑定从XAML或视图模型更新,在这种情况下,我想知道将它包装到自定义WPF FrameworkElement

我所追求的功能是一段文字,表明事情发生的时间。

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

这将呈现为(例如):

  

它发生在1分13秒前

我的代码可以从TimeSpan转换为显示的人类可读形式。

为了让UI每秒都更新,我正在考虑使用静态DispatcherTimer(来自Kent Boogaart's answer的想法)。

所以这就是我所拥有的:

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方法来覆盖和删除事件处理程序。

这里推荐的模式是什么?

2 个答案:

答案 0 :(得分:4)

为什么不在控件的Loaded事件中订阅Tick事件,并在Unloaded事件中取消订阅?

答案 1 :(得分:2)

仅仅因为TextBlock没有实现IDisposable并不意味着你不能自己添加接口要求和实现。您可以自己实施处理(不要覆盖基础上的任何内容)并在那里处理您的计时器。

显然,你将负责处理你的AgeTextBlock类。你可以在windows关闭事件中执行此操作,例如或类似的事情。

(或者,如果您按照MVVM pattern进行操作,并将计时器放在视图模型上,则可以使视图模型具有IDisposable,并将视图绑定到视图模型上的计时器值。)

[编辑:是的,考虑到这一点,我不认为这应该是一个自定义控件,不像Winforms,WPF不需要自定义控件,相反我想我会暴露一个计时器属性view model(可能是一个预先格式化的属性,所以你有一个很好的可读字符串)并将该属性绑定到普通文本框 - 没有自定义控件 - 然后我会使用样式或模板来调整文本框的视觉属性来查看我多么想要。听起来怎么样?]