如何在 WPF 数据绑定中通知日期时间更改事件
本文关键字:时间 日期 事件 通知 WPF 数据绑定 | 更新日期: 2023-09-27 18:31:13
我有一个WPF应用程序,它像这样使用绑定
<DataGridTextColumn Header="BeginDate" Binding="{Binding BeginDate}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding BeginDate, Converter={StaticResource beginDate} }" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
转换器如下
public class ColorBeginDateConverter:IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
try
{
if (value == null) return Brushes.Transparent;
DateTime dateTime = ConvertBackToDateTime(value.ToString()); //Convert Back To DateTime using a private function
var compare = DateTime.Compare(DateTime.Now, dateTime); //Compare the time
if (compare > 0) return Brushes.Orange; else return Brushes.Transparent;
}
catch (Exception)
{
return Brushes.Transparent;
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return "not implemented";
}
问题是我如何观察每天的日期时间变化? 我需要这个颜色转换器自行动态更改它的颜色,但是当 DateTime.Now 更改时,不会通知颜色更改。
此致敬意。非常感谢。
背景颜色取决于更改 DateTime.Now,但在代码中,绑定到 BeginDate 将保持不变。因此,您必须通过在 ViewModel 中触发 PropertyChanged 事件来发送 BeginDate 已显式更改的通知。您可以使用计时器:
DispatcherTimer _timer = null;
。
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += (s, e) => OnPropertyChanged("BeginDate");
_timer.Start();
。
// Do no forget to stop timer when VM is no longer needed to prevent memory leak
_timer.Stop();
更新
以下示例是使用计时器的解决方案的概念证明。带有 BeginDate 的单元格的背景每秒将其颜色从橙色更改为透明一次。EmployeesListViewModel 是带有 DataGrid 的控件的 DataContext。不要忘记为每个 EmployeeDetailsViewModel 调用 StopTimer() 以防止内存泄漏。
XAML
<UserControl.Resources>
<ResourceDictionary>
<local:ColorBeginDateConverter x:Key="beginDate" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<DataGrid Name="gridEmployees" ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="BeginDate" Binding="{Binding BeginDate}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding BeginDate, Converter={StaticResource beginDate} }" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
C#
public class EmployeesListViewModel : INotifyPropertyChanged
{
private ObservableCollection<EmployeeDetailsViewModel> _employees;
public EmployeesListViewModel()
{
_employees = new ObservableCollection<EmployeeDetailsViewModel>();
_employees.Add(new EmployeeDetailsViewModel() { BeginDate = DateTime.Now });
_employees.Add(new EmployeeDetailsViewModel() { BeginDate = DateTime.Now.AddDays(1) });
}
public ObservableCollection<EmployeeDetailsViewModel> Employees
{
get { return _employees; }
}
}
public class EmployeeDetailsViewModel : INotifyPropertyChanged
{
DispatcherTimer _timer = null;
public EmployeeDetailsViewModel()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += (s, e) => { OnPropertyChanged("BeginDate"); };
_timer.Start();
}
public void StopTimer()
{
_timer.Stop();
}
private DateTime _beginDate;
public DateTime BeginDate
{
get { return _beginDate; }
set
{
_beginDate = value;
OnPropertyChanged("BeginDate");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
var e = new PropertyChangedEventArgs(propertyName);
this.PropertyChanged(this, e);
}
}
}
public class ColorBeginDateConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
try
{
if (DateTime.Now.Second % 2 == 0)
return Brushes.Transparent;
else
return Brushes.Orange;
}
catch (Exception)
{
return Brushes.Transparent;
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return "not implemented";
}
}