我正在使用DataTemplate在列表框中顯示項目(通過數據綁定從一個類)。這個類還包含日期和時間,我使用轉換器將此日期/時間轉換爲相對時間(xx分鐘前),然後將其顯示在TextBlock中。到目前爲止,一切都很好。使用WPF DataTemplate更新相對時間
問題是我不知道如何保持這個相對時間更新(它們都被卡在生成的值上,例如「1秒前」)。我可以使用ListBox.Items.Refresh(),但是它也會重新運行我爲這些項目設置的動畫。
任何想法?
在此先感謝!
我正在使用DataTemplate在列表框中顯示項目(通過數據綁定從一個類)。這個類還包含日期和時間,我使用轉換器將此日期/時間轉換爲相對時間(xx分鐘前),然後將其顯示在TextBlock中。到目前爲止,一切都很好。使用WPF DataTemplate更新相對時間
問題是我不知道如何保持這個相對時間更新(它們都被卡在生成的值上,例如「1秒前」)。我可以使用ListBox.Items.Refresh(),但是它也會重新運行我爲這些項目設置的動畫。
任何想法?
在此先感謝!
讓你的模型實現INotifyPropertyChanged
。如果您的雙向綁定設置正確,請撥打OnPropertyChanged
將屬性名稱傳遞給您希望更新的屬性更改。這會提醒任何人查看對該屬性的更改(即您的視圖因此是雙向約束要求),該值已更改且需要更新。
public string Name
{
get { return m_Name; }
set
{
OnPropertyChanged(Name);
m_Name = value;
}
}
更新:
使用一個定時器。我不會從戴夫那裏竊取信息,所以這裏有一個與他的answer相關的鏈接,這個問題非常類似。在你的timer_Tick
方法做你的相對時間計算。這將每秒更新您的GUI。
但是,如果每個項目的時間沒有改變,OnPropertyChanged會工作嗎? (這是在服務器上的項目創建時間) – 2009-12-16 15:37:27
因此,模型上的時間屬性不會更改。我假設你正在使用DateTime.Now進行相對計算,並且你只是想計算主動更新,對嗎? – Ragepotato 2009-12-16 18:20:57
基本上是的:) – 2009-12-16 18:26:00
您需要實施INotifyPropertyChanged
或DependencyProperty
以查看您要綁定的媒體資源才能看到更新。
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.
}
}
您不應該更改DateTime值。你需要的是一個轉換器。 – 2016-04-20 19:46:16
我有同樣的問題剛纔我通過爲這些項目創建一個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)
使用定時器JUST來提高屬性更改事件並使用綁定到該值的轉換器會更有意義嗎?只要計時器引發PropertyChanged事件,轉換器就會自動提取何時轉換並輸出新值。 – 2016-04-20 19:48:14
我決定發佈自己的解決方案,因爲我覺得這是最簡單的,需要比別人我看到更少的代碼。
//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}}"/>
還可以切換該對象是否應該打勾,你可以在對象類中定義一個額外的構造函數或標誌,指示是否啓用了此類行爲。這樣,如果您的應用程序支持更改日期格式,您可以簡單地迭代您的對象,檢查每個標誌,並刪除(或交換)綁定的現有轉換器。
確定這個INotifyPropertyChanged和DependencyProperty的東西是我的頭,所以我改變了用戶界面一點點,以解決這個問題。可能稍後會回到這個位置。謝謝:) – 2009-12-16 16:14:31