如何在 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 更改时,不会通知颜色更改。

此致敬意。非常感谢。

如何在 WPF 数据绑定中通知日期时间更改事件

背景颜色取决于更改 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";
    }
}