如何使用 wrapPanels 在日历中正确显示日期?
How to display days in calendar properly using wrapPanels?
我正在编写 WPF 应用程序。我有一个 Calendar
和 Buttons
用于上个月 (<)、当前 (今天) 和下个月 (>)。我的问题是,当我切换下一个月或上一个月时,每个月的第一天总是在同一天开始。
我有一个面板,我可以在其中创建其他面板。每个面板代表一天。我的代码应该在正确的位置放置一个带有天数的标签,但它总是从第一个 WrapPanel
开始。问题出在哪里?下面是一些屏幕截图。
单击下个月按钮后,二月应从星期四开始。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace ActivityMonitor
{
/// <summary>
/// Logika interakcji dla klasy CalendarWindow.xaml
/// </summary>
public partial class CalendarWindow : Window
{
//lista dni w danym miesiacu
private List<WrapPanel> daysList = new List<WrapPanel>();
//aktualna data
private DateTime currentDate = DateTime.Today;
public CalendarWindow()
{
InitializeComponent();
DisplayCalendar();
}
//metoda wyświetlająca kalendarz
private void DisplayCalendar()
{
GenerateDayPanel(42);
//AddDayLabelToWrap(GetFirstDayOfCurrentDate(), GetTotalDaysOfCurrentDate());
DisplayCurrentDate();
}
//metoda
private int GetFirstDayOfCurrentDate()
{
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
return (int) firstDayOfMonth.DayOfWeek + 1;
}
private int GetTotalDaysOfCurrentDate()
{
DateTime firstDayOfCurrentDate = new DateTime(currentDate.Year, currentDate.Month, 1);
return firstDayOfCurrentDate.AddMonths(1).AddDays(-1).Day;
}
private void DisplayCurrentDate()
{
labelMonthAndYear.Content = currentDate.ToString("MMMM, yyyy");
AddDayLabelToWrap(GetFirstDayOfCurrentDate(), GetTotalDaysOfCurrentDate());
}
//metoda ustawuająca miesiąc na poprzedni
private void PreviousMonth()
{
currentDate = currentDate.AddMonths(-1);
DisplayCurrentDate();
}
//metoda ustawiająca miesiąc na następny
private void NextMonth()
{
currentDate = currentDate.AddMonths(1);
DisplayCurrentDate();
}
//metoda ustawiająca miesiąc na aktualny
private void Today()
{
currentDate = DateTime.Today;
DisplayCurrentDate();
}
//metoda generująca dni tygodnia danego miesiąca
private void GenerateDayPanel(int totalDays)
{
daysPanel.Children.Clear();
daysList.Clear();
for (int i = 1; i <= totalDays; i++)
{
var wrap = new WrapPanel();
wrap.Name = $"wrap{i}";
wrap.ItemWidth = 200;
wrap.ItemHeight = 100;
if(i%2 == 0)
{
wrap.Background = new SolidColorBrush(Colors.LightBlue);
}
else
{
wrap.Background = new SolidColorBrush(Colors.Gray);
}
daysPanel.Children.Add(wrap);
daysList.Add(wrap);
}
}
//metoda dodająca labele z numerami dni miesiąca
private void AddDayLabelToWrap(int startDayAtPanel, int totalDaysInMonth)
{
foreach (WrapPanel wrap in daysList)
{
wrap.Children.Clear();
}
for (int i = 1; i <= totalDaysInMonth; i++)
{
var lab = new Label();
lab.Name = $"lblDay{i}";
lab.Content = i;
lab.HorizontalContentAlignment = HorizontalAlignment.Right;
daysList[(i - 1) + (startDayAtPanel - 1)].Children.Add(lab);
}
}
private void ButtonPrevMonth_Click(object sender, RoutedEventArgs e)
{
PreviousMonth();
}
private void ButtonNextMonth_Click(object sender, RoutedEventArgs e)
{
NextMonth();
}
private void ButtonToday_Click(object sender, RoutedEventArgs e)
{
Today();
}
}
}
我做了你需要的样品,放在了GitHub。
Here.
https://github.com/ncoresoftsource/Whosebugsample/tree/main/src/answers/custom-calendar-app
这并不像我想的那么简单。和其他人的建议一样,把UI写在后面的代码中并不是很长运行的好方法,所以我给你做的这个示例源码希望你好好研究一下!
随便点!
使用列表框
public class CalendarBox : ListBox
{
}
样式和模板
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:CalendarCore.Controls">
<Style TargetType="{x:Type Label}" x:Key="LABEL.WEEK">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0 0 1 1"/>
<Setter Property="BorderBrush" Value="#DDDDDD"/>
<Setter Property="Background" Value="#F1F1F1"/>
<Setter Property="Padding" Value="0 4 0 4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="{TemplateBinding Padding}">
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListBoxItem}" x:Key="LBXI.DAY">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0 0 1 1"/>
<Setter Property="BorderBrush" Value="#DDDDDD"/>
<Setter Property="Padding" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="{TemplateBinding Padding}">
<TextBlock Text="{Binding Day}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#FAFAFA"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#F1F1F1"/>
</Trigger>
<DataTrigger Binding="{Binding IsLastMonth}" Value="True">
<Setter Property="Foreground" Value="#BBBBBB"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsNextMonth}" Value="True">
<Setter Property="Foreground" Value="#BBBBBB"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ctrl:CalendarBox}">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource LBXI.DAY}"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="BorderThickness" Value="1 1 0 0"/>
<Setter Property="BorderBrush" Value="#DDDDDD"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctrl:CalendarBox}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<UniformGrid Columns="7">
<Label Style="{StaticResource LABEL.WEEK}" Content="MON" Background="#FFFFEAEA"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="TUE" Background="#FFE8F9FF"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="WED" Background="#FFE1F1C5"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="THU" Background="#FFFFD7D7"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="FRI" Background="#FFE9F9E4"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="SAT" Background="#FFF7F6E3"/>
<Label Style="{StaticResource LABEL.WEEK}" Content="SUN" Background="#FFC4DAE4"/>
</UniformGrid>
<ItemsPresenter Grid.Row="1"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<UniformGrid Columns="7"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
主窗口 (.xaml)
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="btnPreview" Content="Preview" Margin="4" Padding="4"/>
<Button x:Name="btnNext" Content="Next" Margin="4" Padding="4"/>
</StackPanel>
<ctrl:CalendarBox Grid.Row="1" x:Name="calendar"/>
</Grid>
隐藏代码 (.cs)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using CalendarCore.Enums;
using CalendarCore.Models;
namespace CalendarDemo.Basic
{
public partial class MainWindow : Window
{
private int Year;
private int Month;
public MainWindow()
{
InitializeComponent();
Year = DateTime.Now.Year;
Month = DateTime.Now.Month;
Loaded += (s,e)=> Refresh(CalendarMove.None);
btnPreview.Click += (ps, pe) => Refresh(CalendarMove.Preview);
btnNext.Click += (ns, ne) => Refresh(CalendarMove.Next);
}
private void Refresh(CalendarMove move)
{
DateTime currentDateTime = new DateTime(Year, Month, 1);
int moveMonth = 0;
switch (move)
{
case CalendarMove.None: moveMonth = 0; break;
case CalendarMove.Preview: moveMonth = -1; break;
case CalendarMove.Next: moveMonth = 1; break;
}
Year = currentDateTime.AddMonths(moveMonth).Year;
Month = currentDateTime.AddMonths(moveMonth).Month;
calendar.ItemsSource = GenerateCalendar(Year, Month);
}
private IEnumerable GenerateCalendar(int year, int month)
{
List<DayModel> days = new List<DayModel>();
// Step 1. Add days of last month.
AddDaysOfLastMonth(year, month, ref days);
// Step 2. Add days of current mon.th
AddDaysOfCurrentMonth(year, month, ref days);
// Step 3. Add days of next month.
AddDaysOfNextMonth(year, month, ref days);
return days;
}
private void AddDaysOfLastMonth(int year, int month, ref List<DayModel> days)
{
var lastMonth = new DateTime(year, month, 1).AddMonths(-1);
int dayStarting;
int lastDayOfLastMonth = DateTime.DaysInMonth(lastMonth.Year, lastMonth.Month);
DayOfWeek firstDayOfWeek = new DateTime(year, month, 1).DayOfWeek;
switch (firstDayOfWeek)
{
case DayOfWeek.Monday: dayStarting = 0; break;
case DayOfWeek.Tuesday: dayStarting = 1; break;
case DayOfWeek.Wednesday: dayStarting = 2; break;
case DayOfWeek.Thursday: dayStarting = 3; break;
case DayOfWeek.Friday: dayStarting = 4; break;
case DayOfWeek.Saturday: dayStarting = 5; break;
case DayOfWeek.Sunday: dayStarting = 6; break;
default: dayStarting = 0;break;
}
for (int i = 1; i <= dayStarting; i++)
{
days.Add(new DayModel
{
Date = new DateTime(lastMonth.Year, lastMonth.Month, lastDayOfLastMonth + i - dayStarting),
IsLastMonth = true
});
}
}
private void AddDaysOfCurrentMonth(int year, int month, ref List<DayModel> days)
{
int lastDay = DateTime.DaysInMonth(year, month);
for (int i = 1; i <= lastDay; i++)
{
days.Add(new DayModel { Date = new DateTime(year, month, i) });
}
}
private void AddDaysOfNextMonth(int year, int month, ref List<DayModel> days)
{
var nextMonth = new DateTime(year, month, 1).AddMonths(1);
var lastDayofCurrentMonth = DateTime.DaysInMonth(year, month);
int dayStarting;
DayOfWeek lastDayOfWeek = new DateTime(year, month, lastDayofCurrentMonth).DayOfWeek;
switch (lastDayOfWeek)
{
case DayOfWeek.Monday: dayStarting = 6; break;
case DayOfWeek.Tuesday: dayStarting = 5; break;
case DayOfWeek.Wednesday: dayStarting = 4; break;
case DayOfWeek.Thursday: dayStarting = 3; break;
case DayOfWeek.Friday: dayStarting = 2; break;
case DayOfWeek.Saturday: dayStarting = 1; break;
case DayOfWeek.Sunday: dayStarting = 0; break;
default: dayStarting = 0; break;
}
for (int i = 1; i <= dayStarting; i++)
{
days.Add(new DayModel
{
Date = new DateTime(nextMonth.Year, nextMonth.Month, i),
IsNextMonth = true
});
}
}
}
}
型号
public class DayModel
{
public DateTime Date { get; set; }
public int Year => Date.Year;
public int Month => Date.Month;
public int Day => Date.Day;
public bool IsLastMonth { get; set; }
public bool IsCurrentMonth { get; set; }
public bool IsNextMonth { get; set; }
}
我正在编写 WPF 应用程序。我有一个 Calendar
和 Buttons
用于上个月 (<)、当前 (今天) 和下个月 (>)。我的问题是,当我切换下一个月或上一个月时,每个月的第一天总是在同一天开始。
我有一个面板,我可以在其中创建其他面板。每个面板代表一天。我的代码应该在正确的位置放置一个带有天数的标签,但它总是从第一个 WrapPanel
开始。问题出在哪里?下面是一些屏幕截图。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace ActivityMonitor
{
/// <summary>
/// Logika interakcji dla klasy CalendarWindow.xaml
/// </summary>
public partial class CalendarWindow : Window
{
//lista dni w danym miesiacu
private List<WrapPanel> daysList = new List<WrapPanel>();
//aktualna data
private DateTime currentDate = DateTime.Today;
public CalendarWindow()
{
InitializeComponent();
DisplayCalendar();
}
//metoda wyświetlająca kalendarz
private void DisplayCalendar()
{
GenerateDayPanel(42);
//AddDayLabelToWrap(GetFirstDayOfCurrentDate(), GetTotalDaysOfCurrentDate());
DisplayCurrentDate();
}
//metoda
private int GetFirstDayOfCurrentDate()
{
DateTime firstDayOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1);
return (int) firstDayOfMonth.DayOfWeek + 1;
}
private int GetTotalDaysOfCurrentDate()
{
DateTime firstDayOfCurrentDate = new DateTime(currentDate.Year, currentDate.Month, 1);
return firstDayOfCurrentDate.AddMonths(1).AddDays(-1).Day;
}
private void DisplayCurrentDate()
{
labelMonthAndYear.Content = currentDate.ToString("MMMM, yyyy");
AddDayLabelToWrap(GetFirstDayOfCurrentDate(), GetTotalDaysOfCurrentDate());
}
//metoda ustawuająca miesiąc na poprzedni
private void PreviousMonth()
{
currentDate = currentDate.AddMonths(-1);
DisplayCurrentDate();
}
//metoda ustawiająca miesiąc na następny
private void NextMonth()
{
currentDate = currentDate.AddMonths(1);
DisplayCurrentDate();
}
//metoda ustawiająca miesiąc na aktualny
private void Today()
{
currentDate = DateTime.Today;
DisplayCurrentDate();
}
//metoda generująca dni tygodnia danego miesiąca
private void GenerateDayPanel(int totalDays)
{
daysPanel.Children.Clear();
daysList.Clear();
for (int i = 1; i <= totalDays; i++)
{
var wrap = new WrapPanel();
wrap.Name = $"wrap{i}";
wrap.ItemWidth = 200;
wrap.ItemHeight = 100;
if(i%2 == 0)
{
wrap.Background = new SolidColorBrush(Colors.LightBlue);
}
else
{
wrap.Background = new SolidColorBrush(Colors.Gray);
}
daysPanel.Children.Add(wrap);
daysList.Add(wrap);
}
}
//metoda dodająca labele z numerami dni miesiąca
private void AddDayLabelToWrap(int startDayAtPanel, int totalDaysInMonth)
{
foreach (WrapPanel wrap in daysList)
{
wrap.Children.Clear();
}
for (int i = 1; i <= totalDaysInMonth; i++)
{
var lab = new Label();
lab.Name = $"lblDay{i}";
lab.Content = i;
lab.HorizontalContentAlignment = HorizontalAlignment.Right;
daysList[(i - 1) + (startDayAtPanel - 1)].Children.Add(lab);
}
}
private void ButtonPrevMonth_Click(object sender, RoutedEventArgs e)
{
PreviousMonth();
}
private void ButtonNextMonth_Click(object sender, RoutedEventArgs e)
{
NextMonth();
}
private void ButtonToday_Click(object sender, RoutedEventArgs e)
{
Today();
}
}
}
我做了你需要的样品,放在了GitHub。
Here.
https://github.com/ncoresoftsource/Whosebugsample/tree/main/src/answers/custom-calendar-app
这并不像我想的那么简单。和其他人的建议一样,把UI写在后面的代码中并不是很长运行的好方法,所以我给你做的这个示例源码希望你好好研究一下!
随便点!
使用列表框
public class CalendarBox : ListBox { }
样式和模板
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ctrl="clr-namespace:CalendarCore.Controls"> <Style TargetType="{x:Type Label}" x:Key="LABEL.WEEK"> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="BorderThickness" Value="0 0 1 1"/> <Setter Property="BorderBrush" Value="#DDDDDD"/> <Setter Property="Background" Value="#F1F1F1"/> <Setter Property="Padding" Value="0 4 0 4"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Label}"> <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}"> <TextBlock Text="{TemplateBinding Content}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type ListBoxItem}" x:Key="LBXI.DAY"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderThickness" Value="0 0 1 1"/> <Setter Property="BorderBrush" Value="#DDDDDD"/> <Setter Property="Padding" Value="10"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}"> <TextBlock Text="{Binding Day}" /> </Border> <ControlTemplate.Triggers> <Trigger Property="ItemsControl.AlternationIndex" Value="0"> <Setter Property="Background" Value="#FAFAFA"/> </Trigger> <Trigger Property="ItemsControl.AlternationIndex" Value="1"> <Setter Property="Background" Value="#F1F1F1"/> </Trigger> <DataTrigger Binding="{Binding IsLastMonth}" Value="True"> <Setter Property="Foreground" Value="#BBBBBB"/> </DataTrigger> <DataTrigger Binding="{Binding IsNextMonth}" Value="True"> <Setter Property="Foreground" Value="#BBBBBB"/> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type ctrl:CalendarBox}"> <Setter Property="AlternationCount" Value="2"/> <Setter Property="ItemContainerStyle" Value="{StaticResource LBXI.DAY}"/> <Setter Property="Margin" Value="10"/> <Setter Property="BorderThickness" Value="1 1 0 0"/> <Setter Property="BorderBrush" Value="#DDDDDD"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ctrl:CalendarBox}"> <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <UniformGrid Columns="7"> <Label Style="{StaticResource LABEL.WEEK}" Content="MON" Background="#FFFFEAEA"/> <Label Style="{StaticResource LABEL.WEEK}" Content="TUE" Background="#FFE8F9FF"/> <Label Style="{StaticResource LABEL.WEEK}" Content="WED" Background="#FFE1F1C5"/> <Label Style="{StaticResource LABEL.WEEK}" Content="THU" Background="#FFFFD7D7"/> <Label Style="{StaticResource LABEL.WEEK}" Content="FRI" Background="#FFE9F9E4"/> <Label Style="{StaticResource LABEL.WEEK}" Content="SAT" Background="#FFF7F6E3"/> <Label Style="{StaticResource LABEL.WEEK}" Content="SUN" Background="#FFC4DAE4"/> </UniformGrid> <ItemsPresenter Grid.Row="1"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <UniformGrid Columns="7"/> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
主窗口 (.xaml)
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right"> <Button x:Name="btnPreview" Content="Preview" Margin="4" Padding="4"/> <Button x:Name="btnNext" Content="Next" Margin="4" Padding="4"/> </StackPanel> <ctrl:CalendarBox Grid.Row="1" x:Name="calendar"/> </Grid>
隐藏代码 (.cs)
using System; using System.Collections; using System.Collections.Generic; using System.Windows; using CalendarCore.Enums; using CalendarCore.Models; namespace CalendarDemo.Basic { public partial class MainWindow : Window { private int Year; private int Month; public MainWindow() { InitializeComponent(); Year = DateTime.Now.Year; Month = DateTime.Now.Month; Loaded += (s,e)=> Refresh(CalendarMove.None); btnPreview.Click += (ps, pe) => Refresh(CalendarMove.Preview); btnNext.Click += (ns, ne) => Refresh(CalendarMove.Next); } private void Refresh(CalendarMove move) { DateTime currentDateTime = new DateTime(Year, Month, 1); int moveMonth = 0; switch (move) { case CalendarMove.None: moveMonth = 0; break; case CalendarMove.Preview: moveMonth = -1; break; case CalendarMove.Next: moveMonth = 1; break; } Year = currentDateTime.AddMonths(moveMonth).Year; Month = currentDateTime.AddMonths(moveMonth).Month; calendar.ItemsSource = GenerateCalendar(Year, Month); } private IEnumerable GenerateCalendar(int year, int month) { List<DayModel> days = new List<DayModel>(); // Step 1. Add days of last month. AddDaysOfLastMonth(year, month, ref days); // Step 2. Add days of current mon.th AddDaysOfCurrentMonth(year, month, ref days); // Step 3. Add days of next month. AddDaysOfNextMonth(year, month, ref days); return days; } private void AddDaysOfLastMonth(int year, int month, ref List<DayModel> days) { var lastMonth = new DateTime(year, month, 1).AddMonths(-1); int dayStarting; int lastDayOfLastMonth = DateTime.DaysInMonth(lastMonth.Year, lastMonth.Month); DayOfWeek firstDayOfWeek = new DateTime(year, month, 1).DayOfWeek; switch (firstDayOfWeek) { case DayOfWeek.Monday: dayStarting = 0; break; case DayOfWeek.Tuesday: dayStarting = 1; break; case DayOfWeek.Wednesday: dayStarting = 2; break; case DayOfWeek.Thursday: dayStarting = 3; break; case DayOfWeek.Friday: dayStarting = 4; break; case DayOfWeek.Saturday: dayStarting = 5; break; case DayOfWeek.Sunday: dayStarting = 6; break; default: dayStarting = 0;break; } for (int i = 1; i <= dayStarting; i++) { days.Add(new DayModel { Date = new DateTime(lastMonth.Year, lastMonth.Month, lastDayOfLastMonth + i - dayStarting), IsLastMonth = true }); } } private void AddDaysOfCurrentMonth(int year, int month, ref List<DayModel> days) { int lastDay = DateTime.DaysInMonth(year, month); for (int i = 1; i <= lastDay; i++) { days.Add(new DayModel { Date = new DateTime(year, month, i) }); } } private void AddDaysOfNextMonth(int year, int month, ref List<DayModel> days) { var nextMonth = new DateTime(year, month, 1).AddMonths(1); var lastDayofCurrentMonth = DateTime.DaysInMonth(year, month); int dayStarting; DayOfWeek lastDayOfWeek = new DateTime(year, month, lastDayofCurrentMonth).DayOfWeek; switch (lastDayOfWeek) { case DayOfWeek.Monday: dayStarting = 6; break; case DayOfWeek.Tuesday: dayStarting = 5; break; case DayOfWeek.Wednesday: dayStarting = 4; break; case DayOfWeek.Thursday: dayStarting = 3; break; case DayOfWeek.Friday: dayStarting = 2; break; case DayOfWeek.Saturday: dayStarting = 1; break; case DayOfWeek.Sunday: dayStarting = 0; break; default: dayStarting = 0; break; } for (int i = 1; i <= dayStarting; i++) { days.Add(new DayModel { Date = new DateTime(nextMonth.Year, nextMonth.Month, i), IsNextMonth = true }); } } } }
型号
public class DayModel { public DateTime Date { get; set; } public int Year => Date.Year; public int Month => Date.Month; public int Day => Date.Day; public bool IsLastMonth { get; set; } public bool IsCurrentMonth { get; set; } public bool IsNextMonth { get; set; } }