我在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,而不是选择更改时。
有什么想法吗?
答案 0 :(得分: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;
}
}
该行为基本上会观察CalendarView
的{{1}}事件,并且每次执行该事件时,都会检查所选日期的一周中是否与行为附加的一年中的某一周相匹配至。如果是,我们更改项目的背景。这将在所有日期调用,因此一周中的所有日期都将突出显示。
不幸的是,事实证明你无法通过XAML中的样式设置器附加它:
SelectedDatesChanged
这样,对于创建的第一个项,行为只设置一次。但是,您可以在<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
个实例,并在其认为合适时重复使用它们。