在新的Windows 10日历视图上显示/样式化额外的信息

本文关键字:样式 信息 显示 Windows 日历 视图 | 更新日期: 2023-09-27 18:08:59

我最近开始开发一个Windows 10应用程序,它需要在CalendarView上显示事件和额外的信息。随着新API的发布,还引入了一个新的CalendarView组件,所以我决定尝试一下。这是一个不错的小部件,但自定义一直是一个地狱。

我已经到了可以使用ControlTemplate显示自定义信息的地步,但是用VisualState绑定事件和样式是相当困难的。

这是我用一个样式包装的ControlTemplate。

<Style x:Key="dayItemStyle" TargetType="CalendarViewDayItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="CalendarViewDayItem">
                    <Grid x:Name="DayItemEventListRoot">
                        <ListView ItemsSource="{TemplateBinding DataContext}" Padding="20,0,0,0" x:Name="EventInfoList" 
                                  IsItemClickEnabled="True" cm:Message.Attach="[Event ItemClick] = [ListTapped]">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel x:Name="EventInfoPanel" Orientation="Horizontal">
                                        <TextBlock x:Name="EventTime" Text="{Binding Date, Converter={StaticResource StringFormatter}, ConverterParameter='{0:HH:mm'} }"
                                                  Foreground="{Binding Foreground, RelativeSource={RelativeSource Self}}" >
                                        </TextBlock>
                                        <TextBlock x:Name="EventDesc" Text="{Binding Name}" Padding="5,0,0,0" Foreground="Black" >
                                        </TextBlock>
                                        <VisualStateManager.VisualStateGroups>
                                            <VisualStateGroup>
                                                <VisualState x:Name="Normal" />
                                                <VisualState x:Name="Today" >
                                                    <VisualState.Setters>
                                                        <Setter Target="EventTime.Foreground" Value="White" />
                                                        <Setter Target="EventDesc.Foreground" Value="White" />
                                                        <Setter Target="EventTime.Text" Value="DASFASDDF" />
                                                    </VisualState.Setters>
                                                </VisualState>
                                            </VisualStateGroup>
                                        </VisualStateManager.VisualStateGroups>
                                    </StackPanel>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

然后直接在CalenderView组件上设置样式。

<CalendarView Name="FlowCalendar" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalDayItemAlignment="Top" HorizontalDayItemAlignment="Left"
                  Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="5" Grid.RowSpan="4" CalendarViewDayItemChanging="FlowCalendar_CalendarViewDayItemChanging"
                  CalendarViewDayItemStyle="{StaticResource dayItemStyle}">
</CalendarView>

额外的信息和状态由代码隐藏中的CalenderViewDayItemChanging事件控制。

private void FlowCalendar_CalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
{            
    if(args.Item.Date.Date.Equals(DateTime.Now.Date))
    {
        VisualStateManager.GoToState(args.Item, "Today", false);
        // Testing, gives NullPointerException
        //TextBlock bla = (TextBlock) args.Item.FindName("EventTime");
        //bla.Text = "SDADASFASDF";
    }
    if (args.Phase == 0)
    {
        var eventsByDate = ViewModel.Upcoming.FirstOrDefault(eg => eg.Key.Date == args.Item.Date.Date);
        if (eventsByDate != null)
        {
            args.Item.DataContext = eventsByDate.ToList();
        }
    }
}

设置视觉状态没有任何作用(我已经检查了它是否被调用),将VisualState(Group)移出ControlTemplate只是给了我一个无法找到目标的错误。

我希望通过视觉状态来控制事件列表视图样式,目前是自定义的,因为我不确定CalendarViewDayItem有什么内置状态。我对视觉状态很陌生,所以任何提示都是非常感谢的。

谢谢。

在新的Windows 10日历视图上显示/样式化额外的信息

您的代码将无法工作,因为VisualStateManager.GoToStateControl作为第一个参数;然而,您的VisualStateManager是在Panel类型的StackPanel中定义的。

你将需要实现你自己的VSM,它需要一个Panel代替。看看这篇文章的答案,看看如何做到这一点。

然而,这仍然不能解决你的问题。因为您需要以某种方式找到StackPanel s(注意,因为它在ListView中,可能有多个),然后调用ExtendedVisualStateManager.GoToState . 我建议你把这个模板包装在一个UserControl中(通过这样做,你可能甚至不需要扩展VSM ,因为你可以使用GoToStateAction代替),并有一个依赖属性(IsToday)来控制状态。然后,您可以使用ElementName绑定将CalendarViewDayItem级别的属性传递给IsToday,以便进行状态更改。

更新

我实际上是错误的需要使用ExtendedVisualManager来改变视觉状态。因为它已经在UserControl中了,所以你可以直接调用VisualStateManager.GoToState(this, "statename", flag);

但是,你定义依赖属性的方式是错误的。

用下面的代码替换后面的代码,它应该可以工作。

public bool IsToday
{
    get { return (bool)GetValue(IsTodayProperty); }
    set { SetValue(IsTodayProperty, value); }
}
public static readonly DependencyProperty IsTodayProperty =
    DependencyProperty.Register("IsToday", typeof(bool), typeof(EventListTemplate), new PropertyMetadata(false, OnIsTodayChanged));
static void OnIsTodayChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var template = (EventListTemplate)d;
    if ((bool)e.NewValue)
    {
        var stateset = VisualStateManager.GoToState(template, "DayItemToday", false);
        Debug.WriteLine("did it:", stateset);
    }
}