簡體   English   中英

使用WPF DataTemplate更新相對時間

[英]Updating relative time with WPF DataTemplate

我正在使用DataTemplate在列表框中顯示項目(通過數據綁定從類中)。 該類還包含日期和時間,我正在使用轉換器將此日期/時間轉換為相對時間(xx分鍾前),然后將其顯示在TextBlock中。 到目前為止,一切都很好。

問題是我不知道如何保持此相對時間更新(它們都停留在生成的值上,例如“ 1秒前”)。 我可以使用ListBox.Items.Refresh(),但這也可以重新運行為項目設置的動畫。

有任何想法嗎?

提前致謝!

讓您的模型實現INotifyPropertyChanged 如果您的雙向綁定設置正確,則每當您要更新的屬性發生更改時,請調用OnPropertyChanged並將其傳遞給屬性名稱。 這將提醒正在查看該屬性更改的任何人(即您的視圖,因此具有雙向綁定要求)該值已更改並且需要更新。

public string Name
{
    get { return m_Name; }
    set 
    {
        OnPropertyChanged(Name);
        m_Name = value; 
    }
}

更新:

使用計時器。 我不會從戴夫那里竊取消息來源,因此這是他對類似問題的回答的鏈接。 在您的timer_Tick方法中進行相對時間計算。 這將每秒更新一次GUI。

您需要為要綁定的屬性實現INotifyPropertyChangedDependencyProperty才能查看更新。

DependencyProperty是WPF中的首選方法,因為它將在運行時帶來更好的性能。 這里是文檔 ,包括如何創建示例的示例。

好的,這可能不是最優雅的解決方案(我很確定),但是到目前為止,我已經使用ListBox的ScrollChanged事件在可接受的結果上完成了此操作,只需將每個可見項的時間增加1毫秒,這會導致相對是時候更新了;)每次我向列表框中添加內容時,都會調用該代碼,並且只影響當前可見的項目(類似於VirtualizingStackPanel):)

int VO = 0; // I think that this was protection for when a load of items are added at the beginning. Maybe you can do fine without it.
private void HomeList_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    int v = (int)e.VerticalOffset;
    if (HomeList.Items.Count > 0 && v != VO) // Maybe you can do fine without VO.
    {
        for (int i = 0; i < e.ViewportHeight; i++)
        {
            // Add 1 millisecond to the item's time here
        }
        VO = v; // Maybe you can do fine without VO.
    }
}

我決定發布自己的解決方案,因為我認為它是最簡單的,並且所需的代碼比我所看到的其他代碼少得多。

//AbstractViewModel implements INotifyPropertyChanged
public class MyObject : AbstractViewModel
{
    private DateTime date = DateTime.UtcNow;
    public DateTime Date
    {
        get
        {
            return date;
        }
        set
        {
            date = value;
            OnPropertyChanged("Date");
        }
    }

    public MyObject()
    {
        Timer t = new Timer();
        t.Interval = 1000; //Update every second
        t.Elapsed += T_Elapsed;
        t.Enabled = true;
    }

    private void T_Elapsed(object sender, ElapsedEventArgs e)
    {
        OnPropertyChanged("Date");
    }
}

然后,您將在轉換器內部執行相對時間操作:

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

namespace MyConverters
{
    [ValueConversion(typeof(DateTime), typeof(string))]
    public class RelativeTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            DateTime Date = (DateTime)value;
            if (Date == null) return "never";
            return Utility.RelativeTime(Date);
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

並將轉換器添加到綁定:

<Run Text="{Binding Date, Converter={StaticResource RelativeTimeConverter}}"/>

為了切換對象是否應該打勾,您可以在對象類中定義一個附加的構造函數或標志,以指示是否啟用了這種行為。 這樣,如果您的應用程序支持更改日期格式,則可以簡單地迭代對象,檢查每個對象的標志並刪除(或交換)綁定的現有轉換器。

我現在遇到了同樣的問題,我通過為這些項目創建一個ViewModel來解決了這個問題。

public class MyItem
{
    public DateTime { get; set; }
}

public class MyItemViewModel : INotifyPropertyChanged
{
    private string relativeTime;
    public string RelativeTime
    {
        get { return relativeTime; }
        set
        {
            relativeTime = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("RelativeTime"));
        }
    }

    public DateTime Date { get; set; }

    public static implicit operator MyItemViewModel(MyItem item)
    {
        return new MyItemViewModel { Date = item.Date }
    }
}

然后使用計時器更新它們。

updateRelativeTimeString = new Timer(s =>
    Items.ForEach(
         item => item.RelativeTime = item.Date.ToRelativeTime()),
    null,
    0,
    5000);

使用兩種擴展方法(IEnumerable.ForEach和DateTime.ToRelativeTime)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM