【问题标题】:Is this the efficient way to display list of timers constantly updating the UI?这是显示不断更新 UI 的计时器列表的有效方法吗?
【发布时间】: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


【解决方案1】:

您可以声明一个全局调度程序计时器,而不是为每个项目设置一个计时器,该计时器将每秒更新每个项目(实际上,您应该将延迟设置为低于一秒,否则您可能会看到一些项目跳过一秒)。这将比使用 x 调度程序计时器更有效。您必须将其放入 ViewModel 并使用 foreach 循环进行迭代。您还可以围绕计时器创建一个包装器,定义一个每秒触发的事件,并让所有项目都订阅该事件,但我认为这不值得。

【讨论】:

  • 我已经接受了您的回答,但是如果我在 ViewModel 中使用单个 DispatchTimer,我应该如何处理需要暂停特定计时器的情况?
  • @Nexus 您可以在您的项目上设置一个属性“IsPaused”,并在您遍历它们时检查它。或者考虑对象,使用观察者模式,并在触发计时器事件时让项目自己处理“我暂停”逻辑
  • 谢谢。看看结果如何。
猜你喜欢
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 2012-07-10
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多