ItemsControl 中的 GroupStyle HeaderTemplate 未正确更新
GroupStyle HeaderTemplate in an ItemsControl does not update correctly
我正在为消息收件箱设计布局,目前正在根据 days/weeks/months/years 自动分隔消息。更具体地说,我有一个 header 表示 "Today" 表示在当前日期收到的所有消息,"Yesterday" 表示昨天,“3+ 天前”表示 3 到 6 天前的任何消息。 "Last week" 7-13 天前的任何事,举几个例子。你明白了。
到目前为止,除了一件事,所有这一切都很好。如果我在一夜之间离开应用程序,我今天的消息将被标记为 "Today",但所有旧的 header 都不会改变。所以昨天也被标记为 "Today",2 天前是 "Yesterday" 等等。它们仍然按应有的方式分组,只是标题不会更新。感觉它缺少某种 OnPropertyChanged 功能,但它在当前状态下如何工作?
我的 GroupStyle 是如何设置的:
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="MessageList" Source="{Binding Messages}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="MessageDate" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<Binding Source="{StaticResource MessageList}"/>
</ItemsControl.ItemsSource>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Margin="0 0 0 15">
<TextBlock Text="{Binding Path=Items[0].MessageDate, Converter={StaticResource DateTimeToStringConverter}}"/>
<Path Data="m 0 0 100 0"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
我的转换器(将 DateTime 更改为要显示的字符串)
public class DateTimeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((DateTime)value == DateTime.Now.Date)
{
return "Today";
}
else if ((DateTime)value == DateTime.Now.AddDays(-1).Date)
{
return "Yesterday";
}
else if ((DateTime)value == DateTime.Now.AddDays(-2).Date)
{
return "2 Days Ago";
}
return "3+ Days Ago";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
还可以补充一点,如果我重新启动应用程序,它仍然可以工作,但我不能让它过夜而不发生故障,这太烦人了,无法忽视。
如果您希望它起作用,您需要在每天午夜之前为数据绑定 MessageDate
属性 引发 PropertyChanged
事件。在引发此事件之前不会再次调用转换器。
您可以使用 Quartz.NET or FluentScheduler 等任务调度框架来 运行 在特定时间在您的视图模型中引发事件的代码。
我正在为消息收件箱设计布局,目前正在根据 days/weeks/months/years 自动分隔消息。更具体地说,我有一个 header 表示 "Today" 表示在当前日期收到的所有消息,"Yesterday" 表示昨天,“3+ 天前”表示 3 到 6 天前的任何消息。 "Last week" 7-13 天前的任何事,举几个例子。你明白了。
到目前为止,除了一件事,所有这一切都很好。如果我在一夜之间离开应用程序,我今天的消息将被标记为 "Today",但所有旧的 header 都不会改变。所以昨天也被标记为 "Today",2 天前是 "Yesterday" 等等。它们仍然按应有的方式分组,只是标题不会更新。感觉它缺少某种 OnPropertyChanged 功能,但它在当前状态下如何工作?
我的 GroupStyle 是如何设置的:
<ItemsControl>
<ItemsControl.Resources>
<CollectionViewSource x:Key="MessageList" Source="{Binding Messages}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="MessageDate" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<Binding Source="{StaticResource MessageList}"/>
</ItemsControl.ItemsSource>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Margin="0 0 0 15">
<TextBlock Text="{Binding Path=Items[0].MessageDate, Converter={StaticResource DateTimeToStringConverter}}"/>
<Path Data="m 0 0 100 0"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
我的转换器(将 DateTime 更改为要显示的字符串)
public class DateTimeToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((DateTime)value == DateTime.Now.Date)
{
return "Today";
}
else if ((DateTime)value == DateTime.Now.AddDays(-1).Date)
{
return "Yesterday";
}
else if ((DateTime)value == DateTime.Now.AddDays(-2).Date)
{
return "2 Days Ago";
}
return "3+ Days Ago";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
还可以补充一点,如果我重新启动应用程序,它仍然可以工作,但我不能让它过夜而不发生故障,这太烦人了,无法忽视。
如果您希望它起作用,您需要在每天午夜之前为数据绑定 MessageDate
属性 引发 PropertyChanged
事件。在引发此事件之前不会再次调用转换器。
您可以使用 Quartz.NET or FluentScheduler 等任务调度框架来 运行 在特定时间在您的视图模型中引发事件的代码。