我发现显示定期更新当前时间的唯一方法是使用计时器。当然,我可以实现INotifyPropertyChanged
和一些要在UI上使用的特殊属性,但是此实现AFAIK也需要Timer
。例如here。还有什么更好的方法来显示当前时间?
要澄清一下:是否有任何声明性的方法可以使用这样的XAML语法不使用计时器实时运行它?
<Label Content="{x:Static s:DateTime.Now}" ContentStringFormat="G" />
没有什么可以阻止我在这里使用计时器。我只想知道是否有更优雅,更紧凑的实现方法。
答案 0 :(得分:1)
WPF是一种静态标记语言。据我所知,纯XAML中没有可用的机制来提供您正在寻找的功能。
如果要避免直接使用计时器,可以使用“任务”将其抽象化。
MainWindow XAML:
<Window x:Class="AsyncTimer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AsyncTimer"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Label Content="{Binding CurrentTime}"></Label>
</Grid>
</Window>
后面的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new CurrentTimeViewModel();
}
}
public class CurrentTimeViewModel : INotifyPropertyChanged
{
private string _currentTime;
public CurrentTimeViewModel()
{
UpdateTime();
}
private void UpdateTime()
{
Task.Run(() =>
{
CurrentTime = DateTime.Now.ToString("G");
Task.Delay(1000);
UpdateTime();
});
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string CurrentTime
{
get { return _currentTime; }
set { _currentTime = value; OnPropertyChanged(); }
}
}
这可能是最简洁的一种,而且肯定是您将要获得的“现代” WPF。
答案 1 :(得分:0)
使用Task.Delay会产生很高的CPU使用率!
在XAML代码中输入以下内容:
<Label Name="LiveTimeLabel" Content="%TIME%" HorizontalAlignment="Left" Margin="557,248,0,0" VerticalAlignment="Top" Height="55" Width="186" FontSize="36" FontWeight="Bold" Foreground="Red" />
接下来在xaml.cs中编写以下代码:
[...]
public MainWindow()
{
InitializeComponent();
DispatcherTimer LiveTime = new DispatcherTimer();
LiveTime.Interval = TimeSpan.FromSeconds(1);
LiveTime.Tick += timer_Tick;
LiveTime.Start();
}
void timer_Tick(object sender, EventArgs e)
{
LiveTimeLabel.Content = DateTime.Now.ToString("HH:mm:ss");
}
[...]
答案 2 :(得分:0)
这是一个无需计时器即可运行的小代码示例:
public DateTime CurrentTime
{
get => DateTime.Now;
}
public CurrentViewModelTime(object sender, RoutedEventArgs e)
{
_ = Update(); // calling an async function we do not want to await
}
private async Task Update()
{
while (true)
{
await Task.Delay(100);
OnPropertyChanged(nameof(CurrentTime)));
}
}
当然,此Update()函数永远不会返回,但会在线程池线程上循环,甚至不会长时间阻塞任何线程。
您也可以在没有ViewModel的情况下直接在窗口中完美实现。