如何在WPF数据绑定中通知DateTime更改事件?

时间:2016-01-21 10:22:48

标签: c# wpf datetime binding colors

我有一个使用像这样的绑定的WPF APP

<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改变时,颜色将不会被通知改变。

祝你好运。 非常感谢。

1 个答案:

答案 0 :(得分:4)

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