【问题标题】:Displaying/styling extra info on new Windows 10 CalendarView在新的 Windows 10 CalendarView 上显示/设置额外信息
【发布时间】:2015-11-15 03:42:47
【问题描述】:

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

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

这是我使用的包含在 Style 中的 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 有哪些内置状态。我对视觉状态很陌生,因此非常感谢任何指针。

谢谢。

【问题讨论】:

  • 你到底想做什么?您想要样式化哪些属性? (我不想通过你的 VSM 代码)。
  • 我正在尝试根据 CalendarViewDayItem 可能处于的特定状态设置列表的样式。例如,当天的 DayItem 具有强调的样式,因此我还想设置列表中的 TextBlocks 的样式以同样的方式。
  • 有这方面的消息吗?我有同样的问题(试图在 UWP CalendarView 中显示一些事件信息),但我无法想象你最终是如何只使用这个问题中的信息来做到这一点的:P

标签: c# wpf xaml win-universal-app windows-10


【解决方案1】:

您的代码将不起作用,因为VisualStateManager.GoToStateControl 作为第一个参数;但是,您的VisualStateManager 是在StackPanel 中定义的,其类型为Panel

您需要实现自己的VSM,它采用Panel。请查看this post 的答案,了解如何执行此操作。

但是,这仍然无法解决您的问题。因为您需要以某种方式找到StackPanels(注意,因为它在ListView 内,可能有多个),然后调用ExtendedVisualStateManager.GoToState

我建议您将此模板包装在 UserControl 中(通过这样做,您可能 甚至不需要扩展 VSM as您可以改用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);
    }
}

【讨论】:

  • 感谢您的建议,但我仍然遇到一些问题。到目前为止,我已将 DataTemplate 标记下的所有内容包装到一个单独的 UserControl 中。我向它添加了一个“IsToday”DependencyProperty 并在 UserControl 的“Loaded”事件中检查它并转到相应的 VisualState(使用 ExtendedVisualStateManager )。 GoToState 和 GoToElementState (取决于我是否将 VisualStateGroups 添加到 UserControl 或 StackPanel )总是返回 false 并且未应用样式。还有什么建议吗?
  • 您的用户控件的根面板下是否定义了vsm
  • 我试过直接在 UserControl 和 StackPanel 下定义它(UserControl 的第一个元素也就是根面板)。如果我使用 GetVisualStateGroups,我实际上可以看到 VisualStateGroup,这使得找出问题所在变得更加困难。
  • 也许上传你的uc的代码,我会看看。
  • 像魅力一样工作。谢谢!
猜你喜欢
  • 2020-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 2014-07-26
相关资源
最近更新 更多