与DispatcherTimer关联的绑定问题

时间:2017-09-10 09:46:36

标签: xaml mvvm data-binding uwp

我正在构建一个通用Windows应用程序,它允许用户跟踪在特定任务上花费的时间。

在我的主页上,我绑定了一个包含时间注册的ObservableCollection。当一个任务正在运行时,我想更新每秒花费的时间。

我使用DispatcherTimer(运行正常)来更新所有活动计时器所花费的时间。我已经实现了INotifyPropertyChanged,并且我在属性的setter中触发了PropertyChanged事件,该事件被绑定到我的XAML。

问题

我希望我的UI每秒都会更新,但它只会更新一次 - 每次运行 - 并且会以非常不规则的时间戳进行更新。我认为我的绑定做错了。

非常感谢您的帮助!

MainPage_loaded

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        TimerRepository repository = new TimerRepository();
        this.Timers = await repository.GetTimersAsync();

        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromSeconds(1);
        _timer.Tick += _timer_Tick;
        _timer.Start();
    }

调度程序计时器,1秒刻度处理:

    private void _timer_Tick(object sender, object e)
    {
        if (this.Timers != null)
        {
            foreach (var timer in this.Timers.Where(m => m.IsRunning))
            {
                timer.Tick();
            }
        }
    }

自定义计时器模型

public class SprintTimer : INotifyPropertyChanged
{
    private string _name;
    private DateTime? _timerStarted;

    public event PropertyChangedEventHandler PropertyChanged;

    private TimeSpan _registedTime;
    public TimeSpan RegisteredTime
    {
        get
        {
            return _registedTime;
        }
        set
        {
            _registedTime = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("RegisteredTime"));
        }
    }

    public bool IsRunning
    {
        get
        {
            return this._timerStarted.HasValue;
        }
    }

    public void Start()
    {
        if (!this._timerStarted.HasValue)
        {
            _timerStarted = DateTime.Now;
        }
    }

    public void Tick()
    {
        if (this.IsRunning)
        {
            this.RegisteredTime = DateTime.Now - _timerStarted.Value;
        }
    }
}

XAML

<ScrollViewer BringIntoViewOnFocusChange="False" VerticalScrollBarVisibility="Hidden">
        <StackPanel x:Name="stackPanel" Grid.Row="0" Margin="20 20 20 0">
            <ItemsControl ItemsSource="{x:Bind Timers, Mode=OneWay}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate x:DataType="data:SprintTimer">
                        <Grid BorderThickness="1">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"></ColumnDefinition>
                                <ColumnDefinition Width="*"></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{x:Bind Name}" Grid.Column="0" FontSize="18" VerticalAlignment="Center"></TextBlock>
                            <TextBlock Text="{x:Bind RegisteredTime}" Grid.Column="1" VerticalAlignment="Center" TextAlignment="Right" FontSize="22" Margin="10"></TextBlock>
                            <Button Grid.Column="2" VerticalAlignment="Center" Margin="10" Name="btnStartTimer" Click="btnStartTimer_Click">
                                <SymbolIcon x:Name="icon" Symbol="Play"></SymbolIcon>
                            </Button>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </ScrollViewer>

UI

enter image description here

1 个答案:

答案 0 :(得分:2)

x的默认模式:Bind是OneTime,您需要将Mode=OneWay添加到所有绑定表达式。