|WPF, Grouchy Whining part 2
||[Jan. 3rd, 2009|05:23 pm]
Who would have thought a countdown in a text box would be so frigging hard to implement?
I have a column in a list view. The list view is bound to a list of objects. This column is bound to the estimated date and time to the next change of the object. However, I really wanted to know how long it was until that next change, not what date/time the change would occur on. So, what I really wanted was a countdown.
I dug through WPF and finally settled on the idea that I needed an animation. However, further digging gave me no sign of a countdown related animation. I dove through Google, etc, but no one appeared to have done something like that and posted about it, so I was left to find my own solution.
I tried several things, but I'll just go into what actually worked. I created a CountdownAnimation class derived from AnimationTimeline that had a property allowing the user to specify the time to which it should count down. There are instructions in MSDN on how to create your own AnimationTimeline class, though they're a bit threadbare. I added the property for the relative time, but I was having a hell of a time getting it to work until I realized you needed to implement CreateInstanceCore to propagate the current status of the object to the object created in CreateInstanceCore. Unless you do that, the property might as well not exist.
Next... it's possible for the time to the next change to change, like when the next change is reached and it calculates the new next change time. The animation had to be responsive to that and fix up the countdown appropriately when it happened. According to MSDN, binding the animation's properties to anything is more or less useless, since the second the animation starts it stops listening. I ended up creating my own derived form of TextBlock to own the animation and govern its updates. I added a new dependency property, AnimationStartPoint, a DateTime property that I bound to the next change property on the object. I registered an event handler with the Loaded event for the TextBlock, in which I created the storyboard and animation and started it up. I then added a PropertyChanged handler for the AnimationStartPoint property that restarted the animation.
Man, it sounds so easy, but it's taken me nearly eight hours to get it into a working state. Who would have thought?
Well, as frustrating as this project has been at times, I've certainly learned a lot, and it's given me more faith in my programming skills. I've always been the kind of coder that tries to find code on MSDN so I don't have to figure out how to do it myself. I don't cut & paste code without understanding it, but it's nice to have a working sample to start from... and I think it makes it less likely that I'll accidentally subvert the intent of the framework I'm using. However, with WPF I've found that either people just aren't doing the things I'm doing (which is worrisome in and of itself), they aren't talking about them, or I can't find the people who are talking about them. That meant I had to go about things with quite a bit of trial and error.
Unfortunately, the answers that my new countdown code is giving me aren't the ones I want to see -- it's about one day full day until anything will change. However, at least I have the answers now. ^^