You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中如何绑定DateTime属性并显示其与当前时间的差值

WPF中如何绑定DateTime属性并显示其与当前时间的差值

看起来你想要在WPF列表里绑定DateTime类型的When属性,但显示它和当前时间的相对差值(比如“5分钟前”“2小时前”这种)对吧?我给你几个实用的方案,一步步来:


方案一:使用值转换器(IValueConverter)

这是WPF里处理“数据格式转换”场景最常规的做法,不需要修改你的核心数据模型,只需要新增一个转换器类:

1. 创建时间差值转换器

先写一个实现IValueConverter的类,负责把DateTime转换成友好的时间差字符串:

using System;
using System.Globalization;
using System.Windows.Data;

public class TimeAgoConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is DateTime dateTime)
        {
            var timeSpan = DateTime.Now - dateTime;
            
            // 根据时间差返回不同的友好文本
            if (timeSpan.TotalSeconds < 60)
                return "刚刚";
            if (timeSpan.TotalMinutes < 60)
                return $"{(int)timeSpan.TotalMinutes}分钟前";
            if (timeSpan.TotalHours < 24)
                return $"{(int)timeSpan.TotalHours}小时前";
            if (timeSpan.TotalDays < 30)
                return $"{(int)timeSpan.TotalDays}天前";
            
            // 超过1个月的话显示标准日期格式
            return dateTime.ToString("yyyy-MM-dd HH:mm");
        }
        return string.Empty;
    }

    // 反向转换用不到,直接返回null
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

2. 在XAML中引用并使用转换器

首先在Window的资源里注册这个转换器(注意要在XAML顶部添加local命名空间,指向你的转换器所在的项目命名空间):

<Window.Resources>
    <local:TimeAgoConverter x:Key="TimeAgoConverter"/>
</Window.Resources>

然后在ListBox的ItemTemplate里绑定When属性时,指定这个转换器:

<ListBox x:Name="ltvInfos">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding When, Converter={StaticResource TimeAgoConverter}}" Margin="0 0 10 0"/>
                <TextBlock Text="{Binding What}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

补充:实现实时更新

上面的转换器只会在第一次绑定或When属性变化时计算一次,如果想要时间差自动刷新(比如过了一分钟自动从“刚刚”变成“1分钟前”),可以在MainWindow里加一个定时器:

private DispatcherTimer _updateTimer;

public MainWindow()
{
    InitializeComponent();
    Informations = new ObservableCollection<Information>
    {
        new Information() { When = DateTime.Now, What = "A first information" },
        new Information() { When = DateTime.Now, What = "Another information" },
        new Information() { When = DateTime.Now, What = "An other information" }
    };
    ltvInfos.ItemsSource = Informations;

    // 初始化定时器,每分钟触发一次绑定刷新
    _updateTimer = new DispatcherTimer
    {
        Interval = TimeSpan.FromMinutes(1)
    };
    _updateTimer.Tick += (s, e) =>
    {
        // 通知每个Information对象的When属性“变化”,触发转换器重新计算
        foreach (var info in Informations)
        {
            info.OnPropertyChanged(nameof(Information.When));
        }
    };
    _updateTimer.Start();
}

(需要确保你的Information类的OnPropertyChanged方法是可访问的,比如改成public或者添加专门的刷新方法)


方案二:在数据模型中添加计算属性

如果你觉得转换器的实时刷新逻辑有点繁琐,也可以把时间差计算逻辑封装在Information类里:

1. 修改Information类

新增一个TimeAgo计算属性,同时通过定时器触发实时更新:

using System;
using System.Runtime.CompilerServices;
using System.Windows;

public class Information : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private DateTime _when;
    public DateTime When
    {
        get => _when;
        set
        {
            _when = value;
            OnPropertyChanged();
            // 当When变化时,同步通知TimeAgo更新
            OnPropertyChanged(nameof(TimeAgo));
        }
    }

    public string What { get; set; }

    // 计算属性:返回时间差友好文本
    public string TimeAgo
    {
        get
        {
            var timeSpan = DateTime.Now - When;
            if (timeSpan.TotalSeconds < 60)
                return "刚刚";
            if (timeSpan.TotalMinutes < 60)
                return $"{(int)timeSpan.TotalMinutes}分钟前";
            if (timeSpan.TotalHours < 24)
                return $"{(int)timeSpan.TotalHours}小时前";
            if (timeSpan.TotalDays < 30)
                return $"{(int)timeSpan.TotalDays}天前";
            return When.ToString("yyyy-MM-dd HH:mm");
        }
    }

    // 静态定时器,所有Information实例共用
    private static DispatcherTimer _updateTimer;
    static Information()
    {
        _updateTimer = new DispatcherTimer
        {
            Interval = TimeSpan.FromMinutes(1)
        };
        _updateTimer.Tick += (s, e) =>
        {
            // 这里可以维护一个实例列表来触发所有实例的TimeAgo更新,或者在MainWindow里遍历触发
        };
        _updateTimer.Start();
    }
}

然后在XAML里直接绑定TimeAgo属性即可:

<TextBlock Text="{Binding TimeAgo}" Margin="0 0 10 0"/>

备注:内容来源于stack exchange,提问作者R. Douan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 10:04:30