【问题标题】:UWP: Automatically highlight a whole week in CalendarViewUWP:在 CalendarView 中自动突出显示整周
【发布时间】:2018-07-14 14:04:41
【问题描述】:

我在 UWP 应用程序中使用 CalendarView。它以“月”模式显示。我想要的是,当用户选择一个日期时,它应该以某种方式突出显示所选日期的整个星期。

我能够使用以下代码获得一些东西,该代码在用户选择日期后选择一周中的所有日子,但它看起来不太好,事件处理分离/附加很麻烦且容易出错我相信可能会有更合适的选择:

private void cvMain_SelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
{
    // detach event handler to prevent an endless loop
    this.cvMain.SelectedDatesChanged -= cvMain_SelectedDatesChanged;
    try
    {
        if (args.AddedDates.Count > 0)
        {
            // get first date of selection
            var addedDateOffset = args.AddedDates[0];
            var userSelectedDate = addedDateOffset.Date;

            // get first day of the selected way and the last day
            var startOfWeek = userSelectedDate.StartOfWeek();
            var endOfWeek = userSelectedDate.EndOfWeek();

            var selectedDatesList = new List<DateTimeOffset>();
            selectedDatesList.Add(startOfWeek);
            for (var dateInBetween = startOfWeek; dateInBetween <= endOfWeek; dateInBetween = dateInBetween.AddDays(1))
            {
                selectedDatesList.Add(dateInBetween);
            }
            selectedDatesList.Add(endOfWeek);

            cvMain.SelectedDates.Clear();
            foreach (var selectedDate in selectedDatesList)
            {
                cvMain.SelectedDates.Add(selectedDate);
            }
        }
    }
    finally
    {
        // reattach event handler
        this.cvMain.SelectedDatesChanged += cvMain_SelectedDatesChanged;
    }
}

我不确定我是否真的可以使用开箱即用的控件来完成我想要的操作,因为我们似乎无法直接访问日项目,CalendarViewDayItemChanging 事件仅在 Page_Load 上运行一次,不是在选择更改时。

有什么想法吗?

【问题讨论】:

    标签: uwp calendar selection highlight calendarview


    【解决方案1】:

    我已经想到了一个解决方案,但它不一定是一个好的解决方案,所以我只是把它扔在这里作为替代方案:-D。

    我已经尝试为此创建一个行为。首先你需要安装 Behaviors 包:

    Install-Package Microsoft.Xaml.Behaviors.Uwp.Managed -Version 2.0.0 
    

    现在的行为如下所示:

    public class WeekHighlightBehavior : Behavior
    {
        public CalendarView CalendarControl
        {
            get { return (CalendarView)GetValue(CalendarProperty); }
            set { SetValue(CalendarProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for Calendar.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CalendarProperty =
            DependencyProperty.Register("CalendarControl", typeof(CalendarView), typeof(WeekHighlightBehavior), new PropertyMetadata(0));
    
        protected override void OnAttached()
        {
            base.OnAttached();
            CalendarControl.SelectedDatesChanged += Calendar_SelectedDatesChanged;
        }
    
        private void Calendar_SelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
        {
            var dayItem = this.AssociatedObject as CalendarViewDayItem;
            var calendar = CultureInfo.CurrentUICulture.Calendar;
            bool highlight = false;
            foreach (var date in args.AddedDates)
            {
                if (calendar.GetWeekOfYear(date.DateTime, CalendarWeekRule.FirstDay, DayOfWeek.Monday) ==
                    calendar.GetWeekOfYear(dayItem.Date.DateTime, CalendarWeekRule.FirstDay, DayOfWeek.Monday))
                {
                    highlight = true;
                    break;
                }
            }
    
            if (highlight)
            {
                dayItem.Background = new SolidColorBrush(Colors.Yellow);
            }
            else
            {
                dayItem.Background = null;
            }
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            CalendarControl.SelectedDatesChanged -= Calendar_SelectedDatesChanged;
        }
    }
    

    该行为基本上观察CalendarViewSelectedDatesChanged 事件,并且每次执行它时,它都会检查所选日期的一年中的一周是否与行为所附日期的一年中的一周相匹配。如果是,我们更改项目的背景。这将在所有日期调用,因此一周中的所有日子肯定会突出显示。

    不幸的是,您无法通过 XAML 中的样式设置器附加它:

    <CalendarView x:Name="CalendarView">
        <CalendarView.CalendarViewDayItemStyle>
            <Style TargetType="CalendarViewDayItem">
                <Setter Property="interactivity:Interaction.Behaviors">
                    <Setter.Value>
                        <interactivity:BehaviorCollection>
                            <local:WeekHighlightBehavior CalendarControl="{Binding ElementName=CalendarView}" />
                        </interactivity:BehaviorCollection>
                    </Setter.Value>
                </Setter>
                <Setter Property="Padding" Value="0" />
                <Setter Property="Margin" Value="0" />
    
            </Style>
        </CalendarView.CalendarViewDayItemStyle>
    </CalendarView>
    

    这种方式只设置一次行为,用于创建的第一个项目。但是,您可以在 CalendarViewDayItemChanging 事件的代码隐藏中设置行为:

    private void CalendarView_CalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
    {
        var behavior = new WeekHighlightBehavior();
        behavior.CalendarControl = CalendarView;
        Interaction.GetBehaviors(args.Item).Clear();
        Interaction.GetBehaviors(args.Item).Add(behavior);
    }
    

    我正在手动清除附加的行为,因为我注意到它们没有自动清除,因为 CalendarView 保留了 CalendarDayViewItem 实例并在它认为合适的时候重用它们。

    【讨论】:

    • 谢谢,我能够使用您的示例运行它。现在看起来更好,我认为这是一个干净的解决方案......好吧,如果它可以通过 XAML 工作会很好,但也许在未来版本的 UWP 或行为框架中这将是可能的。
    • 是的,希望这对我来说似乎是一个错误,能够通过 setter 设置它会很有用。如果我们能以某种方式轻松访问CalendarViewDayItems,那就太好了:-D。
    猜你喜欢
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    相关资源
    最近更新 更多