0

I currently use a valueconverters in XAML to display my viewmodel DateTime fields in "x minutes ago" format. I need to have them updated periodically without causing too much overhead. At any one time I have a dozen on screen, and a few dozen off screen. What is the best strategy?

  1. In the constructor of the viewmodel object, have them register themselves to a static 'ViewRefresher' that periodically goes through all the objects and fires PropertyChanged handlers, on the registered fields.

  2. Refresh the content/items control objects that are holding my objects

  3. Something else?

I will go ahead and try both approaches above while I wait for answers and report back in case it helps someone else.

Update: OK, thanks to csteinmueller for putting me on the events path. Much cleaner than registering/deregistering objects. I believe the following strategy should not be leaky.

public class DateTimeC: INotifyPropertyChanged
{
    public DateTime DT {get; set;}
    public event PropertyChangedEventHandler PropertyChanged;

    public DateTimeC(DateTime dt)
    {
        DT = dt;
        ViewRefresher.FiveSecondsTick += () =>
           { PropertyChanged(this, new PropertyChangedEventArgs("DT")); };
    }

}

public delegate void TickHandler();

public static class ViewRefresher
{
    private static DispatcherTimer dt = new DispatcherTimer();
    private static int counter = 0;

    public static event TickHandler FiveSecondsTick;
    public static event TickHandler OneMinuteTick;

    static ViewRefresher()
    {
        dt.Interval = TimeSpan.FromSeconds(5);
        dt.Tick += Tick;
        dt.Start();
    }

    private static void Tick(object sender, EventArgs e)
    {
        if (FiveSecondsTick != null)
            FiveSecondsTick();

        if (counter++ != 12) return;

        counter = 0;

        if (OneMinuteTick != null)
            OneMinuteTick();
    }
}

Would have been nice if I could derive from DateTime directly instead of inlining as a field, but it's sealed.

UPDATE 2: This does seem to have a memory leak after all. You need to unhook event for DateTimeC to be garbage-collected, or use a weak reference.

Jamona Mican
  • 1,574
  • 1
  • 23
  • 54

1 Answers1

1

I would choose a System.Timer object togehther with your first approach (all ViewModels register to a collection or event in a static class)

Timer timer;
AutoResetEvent autoEvent = new AutoResetEvent(true);
TimerCallback callback = new TimerCallback(MyCallback);

timer = new Timer(callback, autoEvent, new TimeSpan(0), new Timespan(5));
csteinmueller
  • 2,427
  • 1
  • 21
  • 32
  • Seems like I will run into garbage collection issues. I won't know when to remove the reference to the viewmodel objects that need refreshing, from the static 'ViewRefresher' object. They will stay alive forever I think. – Jamona Mican May 23 '12 at 10:39
  • You could provide a way to let the viewmodels deregister themself. I'd handle this with an event inside the "RefreshService" class. A nice events tutorial can be found at MSDN http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx. – csteinmueller May 23 '12 at 10:42