如何用DispatcherTimer实现两个TextBlock分别显示偶数/奇数秒
嘿,我来帮你搞定这个WPF计时器的需求!你需要两个TextBlock分别只显示偶数秒、奇数秒的计时值,还得每2秒更新一次。这里给你两种实用的实现方案,按需选就行:
方案一:扩展Model,新增独立属性控制奇偶秒显示
这种方式最直接,在TestTimer里加两个专属属性,分别对应偶数秒和奇数秒的格式化文本,计时器触发时根据当前秒数的奇偶性更新对应属性就行:
修改后的Model代码
public class TestTimer : INotifyPropertyChanged { public TestTimer() { Timer = new DispatcherTimer(); // 把计时器间隔改成2秒,符合你"每2秒更新一次"的需求 Timer.Interval = new TimeSpan(0, 0, 2); Timer.Tick += TimerTick; Timer.Start(); } private DispatcherTimer Timer; // 偶数秒专用显示属性 private string _evenTimeFormat; public string EvenTimeFormat { get { return _evenTimeFormat; } set { _evenTimeFormat = value; OnPropertyChanged(); } } // 奇数秒专用显示属性 private string _oddTimeFormat; public string OddTimeFormat { get { return _oddTimeFormat; } set { _oddTimeFormat = value; OnPropertyChanged(); } } private int _seconds; public int Seconds { get { return _seconds; } set { if(value > -1 && value < 61) { _seconds = value; OnPropertyChanged(); } } } private int _minutes; public int Minutes { get { return _minutes; } set { if (value > -1 && value < 61) { _minutes = value; OnPropertyChanged(); } } } private int _hours; public int Hours { get { return _hours; } set { if (value > -1 && value < 25) { _hours = value; OnPropertyChanged(); } } } private void TimerTick(object sender, EventArgs e) { // 每次增加2秒,对应每2秒更新的节奏 Seconds += 2; if (Seconds >= 60) { Seconds -= 60; Minutes++; if (Minutes >= 60) { Minutes -= 60; Hours++; if (Hours >= 24) Hours = 0; } } var formattedTime = string.Format("{0:00}:{1:00}:{2:00}", Hours, Minutes, Seconds); // 根据秒数奇偶性更新对应属性 if (Seconds % 2 == 0) { EvenTimeFormat = formattedTime; // 如果需要奇数秒TextBlock清空,就打开下面这行 // OddTimeFormat = string.Empty; } else { OddTimeFormat = formattedTime; // 如果需要偶数秒TextBlock清空,就打开下面这行 // EvenTimeFormat = string.Empty; } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } }
修改后的View代码
<Grid> <!-- 绑定偶数秒的专属属性 --> <TextBlock Name="textTimeMiddle" Text="{Binding TestTimer.EvenTimeFormat, UpdateSourceTrigger=PropertyChanged}"/> <!-- 绑定奇数秒的专属属性 --> <TextBlock Name="textTimeBottom" Text="{Binding TestTimer.OddTimeFormat, UpdateSourceTrigger=PropertyChanged}"/> </Grid>
方案二:用ValueConverter过滤显示内容
要是不想改动Model的核心结构,那就用WPF的转换器来做过滤,根据秒数奇偶性决定是否显示内容:
实现转换器类
public class SecondFilterConverter : IValueConverter { // 配置这个转换器是显示偶数秒还是奇数秒 public bool ShowEvenSeconds { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is string timeString && !string.IsNullOrEmpty(timeString)) { // 从格式化的时间字符串里提取秒数 var timeParts = timeString.Split(':'); if (timeParts.Length == 3 && int.TryParse(timeParts[2], out int currentSeconds)) { // 符合条件就返回时间字符串,不符合就返回空 if ((ShowEvenSeconds && currentSeconds % 2 == 0) || (!ShowEvenSeconds && currentSeconds % 2 != 0)) { return timeString; } } } // 不符合条件时返回空,你也可以改成返回上次的有效值,看需求调整 return string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
在View里引用并绑定
先在XAML的资源里声明两个转换器实例,一个管偶数秒,一个管奇数秒:
<Window.Resources> <local:SecondFilterConverter x:Key="EvenSecondFilter" ShowEvenSeconds="True"/> <local:SecondFilterConverter x:Key="OddSecondFilter" ShowEvenSeconds="False"/> </Window.Resources>
然后修改TextBlock的绑定,加上转换器:
<Grid> <TextBlock Name="textTimeMiddle" Text="{Binding TestTimer.TimeFormat, Converter={StaticResource EvenSecondFilter}, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Name="textTimeBottom" Text="{Binding TestTimer.TimeFormat, Converter={StaticResource OddSecondFilter}, UpdateSourceTrigger=PropertyChanged}"/> </Grid>
小提醒
如果你是要每秒更新但只显示对应奇偶秒,就保持Model里的Timer.Interval为1秒;如果是严格每2秒更新一次,记得把Interval改成2秒哦。
内容的提问来源于stack exchange,提问作者Amazing User
相关产品推荐
相关产品推荐

