【发布时间】:2013-09-29 16:42:47
【问题描述】:
我正在显示一个计时器列表,这些计时器会不断更新 UI(每隔一秒)以显示正确的时间。 这是有效的方法吗?从性能的角度来看,如何改进这个过程? 我正在为 windows phone 使用 MVVMLight 工具包。
XAML 代码:
<ListBox ItemsSource="{Binding TimersCollection}"
ItemTemplate="{StaticResource SingleItemTemplate}"/>
这是我的简单项目模板代码,它还有暂停、添加分钟按钮,但为简单起见从此处删除:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="SingleItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CurrentTime.Hours}"/>
<TextBlock Text="H"></TextBlock>
<TextBlock Text="{Binding CurrentTime.Minutes}" />
<TextBlock Text="M"></TextBlock>
<TextBlock Text="{Binding CurrentTime.Seconds}" />
<TextBlock Text="S"></TextBlock>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
这是我在视图中注入的 ViewModel 代码:
public class Page1VM : ViewModelBase
{
private ObservableCollection<MyTimer> _timersCollection = new ObservableCollection<MyTimer>();
public Page1VM()
{
// sample code to simulate collection of timers
for (int i = 1; i < 5; i++)
{
var t = new MyTimer();
t.TotalTimeSpan = new TimeSpan(0, i, 0);
_timersCollection.Add(t);
t.Start();
}
}
public IList<MyTimer> TimersCollection
{
get { return _ghatikatimerscoll; }
}
}
这是 ITimer 交互
public interface ITimer
{
bool Start();
bool Stop();
bool IsRunning { get; set; }
void AddMinute();
}
它的实现
公共类 MyTimer : ViewModelBase, ITimer { 公共时间跨度 TotalTimeSpan { 私人获取;放; }
private readonly DispatcherTimer _myDispatcherTimer;
private TimeSpan _startTime;
public bool IsRunning { get; set; }
public MyTimer()
{
_myDispatcherTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 1) };
_myDispatcherTimer.Tick += _myDispatcherTimer_Tick;
}
private TimeSpan _currentTime;
public TimeSpan CurrentTime
{
get
{
return _currentTime;
}
set
{
_currentTime = value;
RaisePropertyChanged("CurrentTime");
}
}
void _myDispatcherTimer_Tick(object sender, EventArgs e)
{
if (_myDispatcherTimer.IsEnabled)
{
var currenttime = TotalTimeSpan.Add(new TimeSpan(0, 0, 1)) - (DateTime.Now.TimeOfDay - _startTime);
CurrentTime = currenttime;
}
}
public bool Start()
{
_startTime = DateTime.Now.TimeOfDay;
if (_currentTime.TotalSeconds != 0)
{
// resuming after paused
TotalTimeSpan = CurrentTime;
}
IsRunning = true;
_myDispatcherTimer.Start();
return true;
}
public bool Stop()
{
_myDispatcherTimer.Stop();
IsRunning = false;
return true;
}
public void AddMinute()
{
TotalTimeSpan = TotalTimeSpan.Add(new TimeSpan(0, 1, 1));
}
}
基本上,我在屏幕上显示一组计时器,这些计时器会自行更新。列表中的每个项目都有自己的 DispatcherTimer。用户单击每个项目的“暂停”按钮以暂停该特定计时器。用户还可以单击“添加分钟”按钮,为收藏中的特定项目增加 1 分钟。
这种方法对不断更新 UI 是否有效?
【问题讨论】:
-
您可以声明一个全局计时器,每秒更新每个项目,而不是每个项目有一个计时器(实际上,您应该将延迟设置为低于一秒,否则您可能会看到一些项目跳过一秒)。这将比使用 x 调度程序计时器更有效
-
为此,我需要将该计时器放在 ViewModel 中。对 ?这也意味着我需要在 List 上使用 ForEach 循环。另外,您指的是哪个 Timer 对象?那个计时器的 MSDN 链接?
-
只是一个经典的 DispatcherTimer。是的,您必须将其放入 ViewModel 并使用 foreach 循环进行迭代。您还可以在计时器周围创建一个包装器,定义一个每秒触发的事件,并让所有项目都订阅该事件,但我认为这不值得
-
你的意思是观察者模式?
-
是的。使用事件可以轻松完成。
标签: xaml windows-phone-7 windows-phone-8 mvvm-light