Binding to time-dependent properties

后端 未结 3 1396
遇见更好的自我
遇见更好的自我 2020-12-10 12:26

Some time ago i wrote a small widget-like application which was supposed to keep track of tasks, each task had a deadline specified as a DateTime, now if you wa

相关标签:
3条回答
  • 2020-12-10 13:02

    I read your accepted answer, but I was just wondering... why not just disable the bindings for that specific task while in 'Edit' mode so you wouldn't be interrupted? Then simply re-enable that binding when you're either done, or you cancel your edit? That way even if your timer updated every second, who cares?

    As for how to disable them without detaching them (and thus resetting their value), simply define a boolean flag, then in all the DPs that you want to interrupt, check for that flag in the validation logic. If the flag is true and the DependencyObject that it applies to is the one you're editing, block the change to the DP.

    Anyway, this just popped into my head. Haven't actually tested it but it should be an easy thing to try.

    0 讨论(0)
  • 2020-12-10 13:10

    A timer is the only way I can think of. Since this is an interesting question, I'll put my .02 in. I would encapsulate it doing something like this:

    public class CountdownViewModel : INotifyPropertyChanged
    {
        Func<TimeSpan> calc;
        DispatcherTimer timer;
    
        public CountdownViewModel(DateTime deadline)
            : this(() => deadline - DateTime.Now)
        {
        }
    
        public CountdownViewModel(Func<TimeSpan> calculator)
        {
            calc = calculator;
    
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += timer_Tick;
            timer.Start();
        }
    
        void timer_Tick(object sender, EventArgs e)
        {
            var temp = PropertyChanged;
            if (temp != null)
            {
                temp(this, new PropertyChangedEventArgs("CurrentValue"));
            }
        }
    
        public TimeSpan CurrentValue
        {
            get
            {
                var result = calc();
                if (result < TimeSpan.Zero)
                {
                    return TimeSpan.Zero;
                }
                return result;
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    
    public class MyViewModel
    {
        public CountdownViewModel DeadlineCountdown { get; private set; }
    
        public DateTime Deadline { get; set; }
    
        public MyViewModel()
        {
            Deadline = DateTime.Now.AddSeconds(200);
            DeadlineCountdown = new CountdownViewModel(Deadline);
        }
    }
    

    Then you could bind to DeadlineCountdown.CurrentValue directly, or create a CountdownView. You could move the timer to the CountdownView, if you wanted. You could use a static timer so they all update at the same time.

    Edit

    If Deadline is going to change, you would have to construct the countdown like this:

    DeadlineCountdown = new CountdownViewModel(() => this.Deadline - DateTime.Now);
    
    0 讨论(0)
  • 2020-12-10 13:15

    I think what you said in your first paragraph after the code sample is the only reasonable way to make this work in WPF. Set up a timer that Just calls PropertyChanged for the TimeLeft property. The interval would vary based upon your scenario (if you're talking a weekly task list, you probably only need to update it ever 5 minutes or so. If you're talking a task list for the next 30 minutes, you may need to update it every minute or 30 seconds or something.

    That method would avoid the problems you mentioned with the refresh option since only the TimeLeft bindings would be affected. If you had millions of these tasks, I guess the performance penalty would be pretty significant. But if you only had a few dozen or something, updating those bindings every 30 seconds or so would be be a pretty insignificant issue, right?

    Every possibility that I can think of uses either Timers or Animations. The animations would be way too "heavy" as you add tasks to the list. And of the Timer scenarios, the one above seems to be the cleanest, simplest and most practical. Probably just comes down to whether it even works or not for your specific scenario.

    0 讨论(0)
提交回复
热议问题