【发布时间】:2020-09-28 13:40:05
【问题描述】:
我正在尝试创建各种 UWP 秒表,但我一直在更新 UI。
下面是我的模型文件夹中的基本秒表类
public class KuStopWatch : INotifyPropertyChanged
{
public string Name { get; set; }
public DateTime DateCreated = DateTime.UtcNow;
public Guid Id = Guid.NewGuid();
public List<TimeSpan> Laps;
public Stopwatch SwInstance = new Stopwatch();
public TimeSpan SavedState { get; set; }
public DateTime TimeStarted { get; set; }
private string _elapsed;
public string Elapsed
{
get { return _elapsed; }
set { _elapsed = value;
NotifyPropertyChanged();
}
}
public bool ClosedWhileRunning { get; set; }
public void Start()
{
TimeStarted = DateTime.UtcNow;
var tmr = new Timer() { Interval = 16, AutoReset = true };
tmr.Start();
tmr.Elapsed += (s, e) => {
Elapsed = ElapsedString();
};
SwInstance.Start();
}
...
public string ElapsedString()
{
var time = SwInstance.Elapsed + SavedState;
return time.ToString(@"hh\:mm\:ss\:ff");
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
这是我的“ViewModel”
public class StopwatchViewModel : ViewModelBase
{
public ObservableCollection<KuStopWatch> SWData { get; } = new ObservableCollection<KuStopWatch>();
public StopwatchViewModel()
{
//Dummy
SWData.Add(new KuStopWatch());
SWData[0].Start();
}
}
还有我的 XAML
<Page
x:Class="MyApp.Views.StopwatchPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:MyApp.Models"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="StopwatchTemplate" x:DataType="models:KuStopWatch">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Style="{ThemeResource BaseTextBlockStyle}"
Text="{Binding Path=Elapsed, UpdateSourceTrigger=PropertyChanged}" />
<Button
Grid.Row="2"
Grid.Column="1"
Style="{StaticResource ButtonRevealStyle}">
<SymbolIcon Symbol="Play" />
</Button>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<controls:AdaptiveGridView
x:Name="StopwatchViewGrid"
Background="Transparent"
ItemTemplate="{StaticResource StopwatchTemplate}"
ItemsSource="{Binding}"
OneRowModeEnabled="False" />
</Grid>
数据上下文设置为 ViewModel.SWData。
我得到的当前行为是 UI 中的时间仅在我来回切换页面时更新。我搞砸了 INotify... 的方式导致“应用程序调用了一个为不同线程编组的接口”。例外,无论我尝试什么。有谁知道这样做的正确方法吗?
【问题讨论】:
-
接口按照它应该的方式实现,绑定也是。我可以想象计时器有问题,但我从未使用过
-
这很粗糙。您还有其他想法如何实时更新秒表视图吗?我能想到的只是设置一个计时器或使用 sleep() 循环
-
尝试使用 DispatcherTimer。它应该在 UI 线程中运行,而不是在线程池中,就像 Timer 一样
-
你完全正确!在使用 DispatcherTimer 时,它确实按预期工作。所以这毕竟是一个线程问题。谢谢。