前段时间我写了一个类似小部件的应用程序,它应该跟踪任务,每个任务都有一个指定为 DateTime
的截止日期。 ,现在如果您想显示距离截止日期还有多长时间,您可能希望绑定(bind)到“虚拟”(*诅咒 virtual
关键字*)属性,如下所示:
public TimeSpan TimeLeft
{
get { return Deadline - DateTime.Now; }
}
显然,理论上这个属性在每一次滴答声中都会发生变化,并且您希望时不时地更新您的 UI(例如,通过定期为该属性抽出
PropertyChanged
事件)。回到我写小部件时,我每分钟刷新整个任务列表,但这并不理想,因为如果用户与某些项目交互(例如,通过键入绑定(bind)到
Comments
-property 的 TextBox)将被严重中断并且对源的更新会丢失。那么,如果您有这样的时间相关属性,那么更新 UI 的最佳方法可能是什么?
(顺便说一句,我不再使用该应用程序,只是认为这是一个非常有趣的问题)
最佳答案
计时器是我能想到的唯一方法。由于这是一个有趣的问题,我将把我的 .02 放进去。我会像这样封装它:
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);
}
}
然后你可以绑定(bind)到
DeadlineCountdown.CurrentValue
直接,或创建一个CountdownView
.您可以将计时器移至 CountdownView
,如果你愿意。您可以使用静态计时器,以便它们同时更新。编辑
如果
Deadline
将会改变,你必须像这样构建倒计时:DeadlineCountdown = new CountdownViewModel(() => this.Deadline - DateTime.Now);
关于wpf - 绑定(bind)到时间相关的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6123998/