2009-12-15 40 views
1

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

問題是我不知道如何保持這個相對時間更新(它們都被卡在生成的值上,例如「1秒前」)。我可以使用ListBox.Items.Refresh(),但是它也會重新運行我爲這些項目設置的動畫。

任何想法?

在此先感謝!

+0

確定這個INotifyPropertyChanged和DependencyProperty的東西是我的頭,所以我改變了用戶界面一點點,以解決這個問題。可能稍後會回到這個位置。謝謝:) – 2009-12-16 16:14:31

回答

0

讓你的模型實現INotifyPropertyChanged。如果您的雙向綁定設置正確,請撥打OnPropertyChanged將屬性名稱傳遞給您希望更新的屬性更改。這會提醒任何人查看對該屬性的更改(即您的視圖因此是雙向約束要求),該值已更改且需要更新。

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

更新:

使用一個定時器。我不會從戴夫那裏竊取信息,所以這裏有一個與他的answer相關的鏈接,這個問題非常類似。在你的timer_Tick方法做你的相對時間計算。這將每秒更新您的GUI。

+0

但是,如果每個項目的時間沒有改變,OnPropertyChanged會工作嗎? (這是在服務器上的項目創建時間) – 2009-12-16 15:37:27

+0

因此,模型上的時間屬性不會更改。我假設你正在使用DateTime.Now進行相對計算,並且你只是想計算主動更新,對嗎? – Ragepotato 2009-12-16 18:20:57

+0

基本上是的:) – 2009-12-16 18:26:00

0

您需要實施INotifyPropertyChangedDependencyProperty以查看您要綁定的媒體資源才能看到更新。

DependencyProperty是WPF中的首選方法,因爲它會在運行時帶來更好的性能。其中包括如何創建一個示例。

0

好吧,這可能不是最優雅的解決方案(我很確定它),但現在我已經用可以接受的結果使用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. 
    } 
} 
+0

您不應該更改DateTime值。你需要的是一個轉換器。 – 2016-04-20 19:46:16

0

我有同樣的問題剛纔我通過爲這些項目創建一個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)

+0

使用定時器JUST來提高屬性更改事件並使用綁定到該值的轉換器會更有意義嗎?只要計時器引發PropertyChanged事件,轉換器就會自動提取何時轉換並輸出新值。 – 2016-04-20 19:48:14

0

我決定發佈自己的解決方案,因爲我覺得這是最簡單的,需要比別人我看到更少的代碼。

//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}}"/> 

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