Binding to time-dependent properties

后端 未结 3 1400
遇见更好的自我
遇见更好的自我 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: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 calc;
        DispatcherTimer timer;
    
        public CountdownViewModel(DateTime deadline)
            : this(() => deadline - DateTime.Now)
        {
        }
    
        public CountdownViewModel(Func 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);
    

提交回复
热议问题