michaellperry/UpdateControls — pull request #6 by robertvazan (2014-06-24 16:55:38+00:00)
Title: Timers

This is a collection of classes that makes it very easy to create time-dependent GUI state. In order to make controls update their state with time, all references to DateTime.UtcNow in view models should be replaced with FloatingDateTime.UtcNow, which returns FloatingDateTime instead of DateTime.

FloatingDateTime always represents current time rather than some snapshot of it. View models then perform comparisons like 'FloatingDateTime.UtcNow >= mydeadline' where mydeadline is some fixed DateTime. Condition like that will evaluate the same as 'DateTime.UtcNow >= mydeadline', but FloatingDateTime version additionally records dependency with UpdateControls that causes all dependents to refresh whenever result of this comparison changes.

I've implemented fairly comprehensive time algebra that allows doing things like 'FloatingDateTime.UtcNow.AddHours(1)' or 'FloatingDateTime.UtcNow - mydeadline'. These operations create various kinds of objects whose value changes linearly with time. Expressions like FloatingDateTime.UtcNow.Date/Hour also work as expected.

Time-dependent UI is notified a few milliseconds after the point in time that is likely to trigger GUI changes. Clock skew (forward or backward) is reflected in UI within one second. There's FloatingTimeZone base class that allows application-defined time domains. Only UTC is built-in at the moment.

All the code is currently only in WPF project. While I can imagine how to share it among all the platform projects, I have hard time coming up with design that would allow clean inclusion in portable library. Obviously timers themselves are platform-dependent, but FloatingDateTime is largely abstract code. The culprit is FloatingDateTime.UtcNow, which is heavily used everywhere and cannot be implemented without platform dependencies. One possible solution is to ditch DispatcherTimer and use some kind of portable-compatible timer, but then we have to find some way to forward timer callbacks back to GUI thread. Any other ideas?