使用 C# 和 XAML 的 UWP 多个倒计时
UWP multiple Countdowns with C# and XAML
我正在使用 C# 和 XAML 构建一个 UWP 应用程序。在自定义用户控件上,我构建了一个 "list" 更好的 ListView,其中包含 DataTemplate 和内部网格。
在这个网格中,我有多个带有数据绑定的 TextBlock。在每个生成的行中,我现在想要一个从 DateTimeOffset.Now 到未来(或过去 - 负值)的特定 DateTimeOffset 的倒数计时器。
我尝试用文本 属性 构建一个 class CountDownElement,并用该字符串调用我的 "countdown" Class。在 Xaml 中,我在 TextBlock 中对该字符串进行了数据绑定。
但它并没有改变。我认为 tghe UI 没有更新?有没有不同的方法 - 也许只用 XAML 构建倒计时并将其值绑定到 ViewModel 的生成值?
感谢您的帮助!
这是我的倒计时Class:
public class Countdown
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private string _tb;
private readonly DateTimeOffset _endTime;
public Countdown(string tb, DateTimeOffset endTime)
{
_tb = tb;
_endTime = endTime;
DispatcherTimerSetup();
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
_tb = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
_tb = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
}
这是我的倒计时元素,我在其中创建了一个新的倒计时对象:
public class ListCountdownElement
{
public string CountdownElement;
public ListCountdownElement(Incident incident, int type)
{
CountdownElement = "Countdown";
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
CountdownElement.Foreground = new SolidColorBrush(Colors.Green);
CountdownElement.Text = "sent";
}
else
{
var endTime = incident.Firstresponsebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
break;
default:
break;
}
}
}
这是 IncidentViewModel,我在其中创建倒计时元素 - 这是我绑定到的数据。
public class IncidentViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Customer { get; set; }
public ListStatusBar StatusBar { get; set; }
public ListCountdownElement Countdown { get; set; }
public ListStatusLight Status { get; set; }
public IncidentViewModel(Incident incident, IncidentTypes type)
{
this.Id = incident.Ticketnumber;
this.Title = incident.Title;
this.Customer = incident.Customerid_account.Name;
this.StatusBar = new ListStatusBar(incident, type);
this.Countdown = new ListCountdownElement(incident, type.GetHashCode());
this.Status = new ListStatusLight(incident, type);
}
}
这是 ListViewModel,我在其中获取数据并创建 incidentViewModel 并将它们放入可观察的集合中:
public class IncidentListViewModel
{
public ObservableCollection<Incident> Incidents;
public ObservableCollection<IncidentViewModel> IncidentsCollection;
public IncidentListViewModel()
{
IncidentsCollection = new ObservableCollection<IncidentViewModel>();
}
public async Task<ObservableCollection<IncidentViewModel>> GetData(string accessToken, IncidentTypes type)
{
Incidents = await DataLoader.LoadIncidentsData(accessToken, type.GetHashCode());
IncidentsCollection.Clear();
foreach (var incident in Incidents)
{
var incidentVm = new IncidentViewModel(incident, type);
IncidentsCollection.Add(incidentVm);
}
return IncidentsCollection;
}
}
这是列表控件的 xaml.cs,我在其中绑定到可观察集合:
public sealed partial class IncidentListControl : UserControl
{
private readonly IncidentListViewModel _incidentListVm;
private readonly string _accessToken;
private readonly IncidentTypes _type;
public IncidentListControl(string accessToken, IncidentTypes type)
{
this.InitializeComponent();
this._accessToken = accessToken;
this._type = type;
this.ListHeader.Text = type.ToString();
_incidentListVm = new IncidentListViewModel();
GetIncidentData();
//Get Incident Data and update UI
var period = TimeSpan.FromSeconds(60);
var periodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (source) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.High,
GetIncidentData);
}, period);
}
private async void GetIncidentData()
{
await _incidentListVm.GetData(_accessToken, _type);
this.ListViewIncidents.ItemsSource = _incidentListVm.IncidentsCollection;
}
}
最后 xaml,我在其中对 TextBlocks 进行绑定:
<ListView Name="ListViewIncidents" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Id}" Margin="3" Grid.Column="0" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<TextBlock Text="{Binding Title}" Margin="3" Grid.Column="1" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<TextBlock Text="{Binding Customer}" Margin="3" Grid.Column="2" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<Border Margin="3" Grid.Column="3" Height="10" BorderThickness="1" BorderBrush="Black">
<Rectangle Fill="{Binding StatusBar.Color}" Width="{Binding StatusBar.Width}" HorizontalAlignment="Left" Height="10"></Rectangle>
</Border>
<TextBlock Text="{Binding Countdown.CountdownElement}" Margin="3" Grid.Column="4" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<Ellipse Margin="3" Height="10" Width="10" Stroke="Black" Fill="{Binding Status.StatusColor}" Grid.Column="5"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这只是相关部分。
希望这次更新对您有所帮助!
更新代码:
Countdown.cs
public class Countdown : INotifyPropertyChanged
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private string _tb;
public string Tb
{
get { return _tb; }
set
{
if (Equals(value, _tb))
return;
_tb = value;
OnPropertyChanged();
}
}
private readonly DateTimeOffset _endTime;
public Countdown( DateTimeOffset endTime)
{
// _tb = tb;
_endTime = endTime;
DispatcherTimerSetup();
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
Tb = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
Tb = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ListCountdownElement.cs
public class ListCountdownElement
{
private Countdown _countDown;
public string CountdownElement
{
get {return _countDown.Tb ; }
}
public ListCountdownElement(Incident incident, int type)
{
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown( (DateTimeOffset)endTime);
}
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
//CountdownElement = "sent"; --> think about that later
}
else
{
var endTime = incident.Firstresponsebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown( (DateTimeOffset)endTime);
}
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown((DateTimeOffset)endTime);
}
}
break;
default:
break;
}
}
}
IncidentViewModel.cs
public class IncidentViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Customer { get; set; }
public ListStatusBar StatusBar { get; set; }
public ListCountdownElement Countdown { get; set; }
public ListStatusLight Status { get; set; }
public IncidentViewModel(Incident incident, IncidentTypes type)
{
this.Id = incident.Ticketnumber;
this.Title = incident.Title;
this.Customer = incident.Customerid_account.Name;
this.StatusBar = new ListStatusBar(incident, type);
this.Countdown = new ListCountdownElement(incident, type.GetHashCode());
this.Status = new ListStatusLight(incident, type);
}
}
IncidentListControl.xaml.cs、IncidentListControl.xaml.cs 和 IncidentListViewModel.cs 未受影响
编辑:最终版本
新 ListCountdownElement.cs:
public class ListCountdownElement : INotifyPropertyChanged
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private DateTimeOffset _endTime;
private string _countdownElement;
public string CountdownElement
{
get { return _countdownElement; }
set
{
if (Equals(value, _countdownElement))
return;
_countdownElement = value;
OnPropertyChanged();
}
}
public ListCountdownElement(Incident incident, int type)
{
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
_endTime = (DateTimeOffset)incident.Resolvebykpiid.Failuretime;
DispatcherTimerSetup();
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
//CountdownElement = "sent"; --> think about that later
}
else
{
_endTime = (DateTimeOffset)incident.Firstresponsebykpiid.Failuretime;
DispatcherTimerSetup();
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
_endTime = (DateTimeOffset)incident.Resolvebykpiid.Failuretime;
DispatcherTimerSetup();
}
break;
default:
break;
}
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
CountdownElement = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
CountdownElement = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
看来您没有触发正确的事件来让 ui 知道文本已更改。
您显示的代码对于您要完成的任务来说看起来也有点复杂...
首先确保 CountDown class 继承 INotifyPropertyChanged
。添加该接口时,您还需要向该接口添加以下代码 class:
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
之后,将 _tb 字段更改为实际的 属性,如下所示:
private string _tb;
public string Tb
{
get { return _tb; }
set
{
if(Equals(value, _tb))
return;
_tb = value;
OnPropertyChanged();
}
}
**** 重要 ****
在dispatcherTimer_Tick事件中,改变Tb的值(属性),而不是_tb字段。
现在您需要将 属性 路由到 UI,因此在 ListCountdownElement class 中,也将 CountdownElement 字段更改为真实的 属性。
public string CountdownElement
{ get { return _countDown.Tb; } }
唯一要做的就是添加一个 CountDown 类型的 _countDown 字段,并确保在您的 ListCountdownElement 构造函数中分配它。
我想这应该可以解决它...(虽然没有测试 :))
我正在使用 C# 和 XAML 构建一个 UWP 应用程序。在自定义用户控件上,我构建了一个 "list" 更好的 ListView,其中包含 DataTemplate 和内部网格。 在这个网格中,我有多个带有数据绑定的 TextBlock。在每个生成的行中,我现在想要一个从 DateTimeOffset.Now 到未来(或过去 - 负值)的特定 DateTimeOffset 的倒数计时器。
我尝试用文本 属性 构建一个 class CountDownElement,并用该字符串调用我的 "countdown" Class。在 Xaml 中,我在 TextBlock 中对该字符串进行了数据绑定。 但它并没有改变。我认为 tghe UI 没有更新?有没有不同的方法 - 也许只用 XAML 构建倒计时并将其值绑定到 ViewModel 的生成值?
感谢您的帮助!
这是我的倒计时Class:
public class Countdown
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private string _tb;
private readonly DateTimeOffset _endTime;
public Countdown(string tb, DateTimeOffset endTime)
{
_tb = tb;
_endTime = endTime;
DispatcherTimerSetup();
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
_tb = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
_tb = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
}
这是我的倒计时元素,我在其中创建了一个新的倒计时对象:
public class ListCountdownElement
{
public string CountdownElement;
public ListCountdownElement(Incident incident, int type)
{
CountdownElement = "Countdown";
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
CountdownElement.Foreground = new SolidColorBrush(Colors.Green);
CountdownElement.Text = "sent";
}
else
{
var endTime = incident.Firstresponsebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
var c = new Countdown(CountdownElement, (DateTimeOffset)endTime);
}
}
break;
default:
break;
}
}
}
这是 IncidentViewModel,我在其中创建倒计时元素 - 这是我绑定到的数据。
public class IncidentViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Customer { get; set; }
public ListStatusBar StatusBar { get; set; }
public ListCountdownElement Countdown { get; set; }
public ListStatusLight Status { get; set; }
public IncidentViewModel(Incident incident, IncidentTypes type)
{
this.Id = incident.Ticketnumber;
this.Title = incident.Title;
this.Customer = incident.Customerid_account.Name;
this.StatusBar = new ListStatusBar(incident, type);
this.Countdown = new ListCountdownElement(incident, type.GetHashCode());
this.Status = new ListStatusLight(incident, type);
}
}
这是 ListViewModel,我在其中获取数据并创建 incidentViewModel 并将它们放入可观察的集合中:
public class IncidentListViewModel
{
public ObservableCollection<Incident> Incidents;
public ObservableCollection<IncidentViewModel> IncidentsCollection;
public IncidentListViewModel()
{
IncidentsCollection = new ObservableCollection<IncidentViewModel>();
}
public async Task<ObservableCollection<IncidentViewModel>> GetData(string accessToken, IncidentTypes type)
{
Incidents = await DataLoader.LoadIncidentsData(accessToken, type.GetHashCode());
IncidentsCollection.Clear();
foreach (var incident in Incidents)
{
var incidentVm = new IncidentViewModel(incident, type);
IncidentsCollection.Add(incidentVm);
}
return IncidentsCollection;
}
}
这是列表控件的 xaml.cs,我在其中绑定到可观察集合:
public sealed partial class IncidentListControl : UserControl
{
private readonly IncidentListViewModel _incidentListVm;
private readonly string _accessToken;
private readonly IncidentTypes _type;
public IncidentListControl(string accessToken, IncidentTypes type)
{
this.InitializeComponent();
this._accessToken = accessToken;
this._type = type;
this.ListHeader.Text = type.ToString();
_incidentListVm = new IncidentListViewModel();
GetIncidentData();
//Get Incident Data and update UI
var period = TimeSpan.FromSeconds(60);
var periodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (source) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.High,
GetIncidentData);
}, period);
}
private async void GetIncidentData()
{
await _incidentListVm.GetData(_accessToken, _type);
this.ListViewIncidents.ItemsSource = _incidentListVm.IncidentsCollection;
}
}
最后 xaml,我在其中对 TextBlocks 进行绑定:
<ListView Name="ListViewIncidents" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Id}" Margin="3" Grid.Column="0" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<TextBlock Text="{Binding Title}" Margin="3" Grid.Column="1" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<TextBlock Text="{Binding Customer}" Margin="3" Grid.Column="2" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<Border Margin="3" Grid.Column="3" Height="10" BorderThickness="1" BorderBrush="Black">
<Rectangle Fill="{Binding StatusBar.Color}" Width="{Binding StatusBar.Width}" HorizontalAlignment="Left" Height="10"></Rectangle>
</Border>
<TextBlock Text="{Binding Countdown.CountdownElement}" Margin="3" Grid.Column="4" FontWeight="Bold" FontSize="12" TextWrapping="Wrap" />
<Ellipse Margin="3" Height="10" Width="10" Stroke="Black" Fill="{Binding Status.StatusColor}" Grid.Column="5"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这只是相关部分。 希望这次更新对您有所帮助!
更新代码: Countdown.cs
public class Countdown : INotifyPropertyChanged
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private string _tb;
public string Tb
{
get { return _tb; }
set
{
if (Equals(value, _tb))
return;
_tb = value;
OnPropertyChanged();
}
}
private readonly DateTimeOffset _endTime;
public Countdown( DateTimeOffset endTime)
{
// _tb = tb;
_endTime = endTime;
DispatcherTimerSetup();
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
Tb = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
Tb = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ListCountdownElement.cs
public class ListCountdownElement
{
private Countdown _countDown;
public string CountdownElement
{
get {return _countDown.Tb ; }
}
public ListCountdownElement(Incident incident, int type)
{
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown( (DateTimeOffset)endTime);
}
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
//CountdownElement = "sent"; --> think about that later
}
else
{
var endTime = incident.Firstresponsebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown( (DateTimeOffset)endTime);
}
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
var endTime = incident.Resolvebykpiid.Failuretime;
if (endTime != null)
{
_countDown = new Countdown((DateTimeOffset)endTime);
}
}
break;
default:
break;
}
}
}
IncidentViewModel.cs
public class IncidentViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public string Customer { get; set; }
public ListStatusBar StatusBar { get; set; }
public ListCountdownElement Countdown { get; set; }
public ListStatusLight Status { get; set; }
public IncidentViewModel(Incident incident, IncidentTypes type)
{
this.Id = incident.Ticketnumber;
this.Title = incident.Title;
this.Customer = incident.Customerid_account.Name;
this.StatusBar = new ListStatusBar(incident, type);
this.Countdown = new ListCountdownElement(incident, type.GetHashCode());
this.Status = new ListStatusLight(incident, type);
}
}
IncidentListControl.xaml.cs、IncidentListControl.xaml.cs 和 IncidentListViewModel.cs 未受影响
编辑:最终版本 新 ListCountdownElement.cs:
public class ListCountdownElement : INotifyPropertyChanged
{
public DispatcherTimer DispatcherTimer;
public DateTimeOffset StartTime;
private TimeSpan _time;
private DateTimeOffset _endTime;
private string _countdownElement;
public string CountdownElement
{
get { return _countdownElement; }
set
{
if (Equals(value, _countdownElement))
return;
_countdownElement = value;
OnPropertyChanged();
}
}
public ListCountdownElement(Incident incident, int type)
{
switch (type)
{
case 1:
if (incident.Resolvebykpiid != null)
{
_endTime = (DateTimeOffset)incident.Resolvebykpiid.Failuretime;
DispatcherTimerSetup();
}
break;
case 2:
if (incident.Firstresponsebykpiid != null)
{
if (incident.Firstresponsesent != null && incident.Firstresponsesent.Value)
{
//CountdownElement = "sent"; --> think about that later
}
else
{
_endTime = (DateTimeOffset)incident.Firstresponsebykpiid.Failuretime;
DispatcherTimerSetup();
}
}
break;
case 3:
if (incident.Resolvebykpiid != null)
{
_endTime = (DateTimeOffset)incident.Resolvebykpiid.Failuretime;
DispatcherTimerSetup();
}
break;
default:
break;
}
}
private void DispatcherTimerSetup()
{
DispatcherTimer = new DispatcherTimer();
StartTime = DateTimeOffset.Now;
_time = new TimeSpan();
_time = _endTime - StartTime;
DispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
DispatcherTimer.Tick += dispatcherTimer_Tick;
DispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, object e)
{
_time = _time.Subtract(new TimeSpan(0, 0, 1));
if (_time <= TimeSpan.Zero)
{
CountdownElement = "- " + _time.ToString(@"dd\:hh\:mm\:ss");
}
else
{
CountdownElement = " " + _time.ToString(@"dd\:hh\:mm\:ss");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
看来您没有触发正确的事件来让 ui 知道文本已更改。 您显示的代码对于您要完成的任务来说看起来也有点复杂...
首先确保 CountDown class 继承 INotifyPropertyChanged
。添加该接口时,您还需要向该接口添加以下代码 class:
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
之后,将 _tb 字段更改为实际的 属性,如下所示:
private string _tb;
public string Tb
{
get { return _tb; }
set
{
if(Equals(value, _tb))
return;
_tb = value;
OnPropertyChanged();
}
}
**** 重要 ****
在dispatcherTimer_Tick事件中,改变Tb的值(属性),而不是_tb字段。
现在您需要将 属性 路由到 UI,因此在 ListCountdownElement class 中,也将 CountdownElement 字段更改为真实的 属性。
public string CountdownElement
{ get { return _countDown.Tb; } }
唯一要做的就是添加一个 CountDown 类型的 _countDown 字段,并确保在您的 ListCountdownElement 构造函数中分配它。
我想这应该可以解决它...(虽然没有测试 :))