我有一个使用像这样的绑定的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改变时,颜色将不会被通知改变。
祝你好运。 非常感谢。
答案 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";
}
}