3

我发现定期显示当前时间更新的唯一方法是使用计时器。当然,我可以INotifyPropertyChanged在 UI 上实现一些特殊属性,但是这个实现 AFAIK 也需要Timer. 例如像这里。有没有更好的方法来显示当前时间?

编辑

澄清一下:是否有任何声明性方式可以使其实时工作而无需使用像这样的 XAML 语法的计时器?

<Label Content="{x:Static s:DateTime.Now}" ContentStringFormat="G" />

没有什么能阻止我在这里使用计时器。我只想知道是否有更优雅和更紧凑的方式来实现这一点。

4

3 回答 3

10

使用 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");
}
[...]
于 2019-01-07T16:25:30.360 回答
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() 函数永远不会返回,但它在线程池线程上执行循环,甚至不会长时间阻塞任何线程。

您也可以在没有视图模型的情况下直接在窗口中完美地实现它。

于 2020-02-01T09:11:07.443 回答
0

WPF 是一种静态标记语言。据我所知,纯 XAML 中没有可用的机制来提供您正在寻找的功能。

如果您想避免直接使用计时器,您可以使用 Tasks 将其抽象出来。

主窗口 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 async void UpdateTime()
    {
        CurrentTime = DateTime.Now.ToString("G");
        await 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 之一。

于 2018-06-26T12:37:02.677 回答