Question

This question is similar to another one I asked, but whereas in that case I wanted to know about forcing a binding to update from XAML or a view model, in this case I'd like to know about wrapping this up into a custom WPF FrameworkElement.

The functionality I'm after is a span of text that indicates how long ago something happened.

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

This would render as (for example):

It happened 1 min 13 sec ago

I have code that converts from a TimeSpan to the human-readable form shown.

In order to have the UI update every second I'm considering using a static DispatcherTimer (idea from Kent Boogaart's answer).

So here's what I have:

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?
}

The comment indicates my problem. I can't see how I'd clean up properly with this approach. There's no Dispose method to override and remove the event handler.

What is the recommended pattern here?

Was it helpful?

Solution

Why not subscribe to the Tick event in the Loaded event of the control, and unsubscribe in the Unloaded event ?

OTHER TIPS

Just because TextBlock doesn't implement IDisposable doesn't mean you can't add the interface requirement and the implementation yourself. You can implement dispose yourself (not overriding anything from the base) and dispose of your timer there.

You will Obviously then be responsible for disposing of your AgeTextBlock class. You'll could do this in your windows closing event for example or something like that.

(Alternately, if you follow the MVVM pattern, and put your timer on the view model, you could make your view model IDisposable and just bind the view to the timer value on the view model.)

[Edit: Yeah, thinking about this, I don't really think this should be a custom control unlike Winforms, WPF doesn't have such a need for custom controls, instead I think I would expose a timer property on my view model (Possibly a pre-formatted property so you have a nice readable string) and bind that property to a normal text box - no custom control - then I would use a style or template to tweak the visual properties of the text box to look how I wanted. How does that sound?]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top