我正在使用下面的代码来获取使用 wpf DataGrid 的员工的年度考勤仪表板详细信息。实际问题是将数据与 wpf datagrid 列绑定(bind)很困惑。我想动态生成所有网格列并绑定(bind)数据放入其中。我的要求是在列标题中显示天数,每行数据的起始位置应基于每月的第一天。为了更清晰,请查找附加图像。
我是否应该为每个列生成模型,例如第一个星期日、第一个星期一以及每周的第五个星期六,以绑定(bind)该列,或者是否有任何其他方法可以轻松完成。 任何帮助将不胜感激。
下面的代码用于生成带有假期详细信息的所有日期和月份名称
public class DashboardDateDetails
{
public bool IsHoliday { get; set; }
public string DayName { get; set; }
public string ShortDate { get; set; }
public DateTime Date { get; set; }
public string MonthWithYear { get; set; }
public string ReasonForHoliday { get; set; }
}
//输入参数 HolidaysList 将保存一年中的假期列表。此方法将返回所选年份从 1 月 1 日到 12 月 31 日的日期和日期以及假期详细信息。
private List<DashboardDateDetails> GetDashBoardData(List<KeyValuePair<string,DateTime>> HolidaysList)
{
List<DashboardDateDetails> MonthList = new List<DashboardDateDetails>();
int CurrentYear = DateTime.Now.Year;
DateTime FirstDateOfYear = new DateTime(CurrentYear,01,01);
System.Globalization.CultureInfo Culture = new System.Globalization.CultureInfo("en-US");
string[] DayNames = Culture.DateTimeFormat.AbbreviatedDayNames;
string[] MonthNames = Culture.DateTimeFormat.MonthNames;
string FirstDayNameOfYear = DayNames[(int)FirstDateOfYear.DayOfWeek];
for (int MonthCount = 1; MonthCount <= 12; MonthCount++)
{
int NumberOfDaysInMonth = DateTime.DaysInMonth(CurrentYear, MonthCount);
for (int DayCount = 1; DayCount <= NumberOfDaysInMonth; DayCount++)
{
DashboardDateDetails DateDetails = new DashboardDateDetails();
DateTime CurrentDate = new DateTime(CurrentYear, MonthCount, DayCount);
DateDetails.DayName = DayNames[(int)CurrentDate.DayOfWeek];
DateDetails.Date = CurrentDate;
DateDetails.ShortDate = CurrentDate.ToShortDateString();
DateDetails.MonthWithYear = MonthNames[(int)CurrentDate.Month - 1];
if (HolidaysList != null && HolidaysList.Any())
{
var HolidayDate = HolidaysList.Where(a => a.Value.ToShortDateString() == CurrentDate.ToShortDateString());
DateDetails.IsHoliday = HolidayDate != null && HolidayDate.Any();
DateDetails.ReasonForHoliday = HolidayDate != null && HolidayDate.Count() > 0 ? HolidayDate.First().Key : string.Empty;
}
MonthList.Add(DateDetails);
}
}
return MonthList;
}
最佳答案
您好,以下实现与您想要的不完全相同,但我希望它能给您一个想法。我没有继续风格,只是想给您一个逻辑概念。
xaml
<DataGrid AutoGenerateColumns="False" x:Name="dataGrid" IsReadOnly="True" ItemsSource="{Binding DashboardDates}"/>
xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//Creat datagrid columns.Can also be done in xaml. but for short i have done in .cs
CreateCoulmns();
DataContext = new ViewModel();
}
void CreateCoulmns()
{
var converter = new BackGroundConverter();
for (int i = -1; i < 35; i++)
{
DataGridTextColumn dataGridTextColumn = new DataGridTextColumn();
if (i == -1)
{
dataGridTextColumn.Header = "Month / Day";
dataGridTextColumn.Binding = new Binding("MonthName");
}
else
{
switch (i % 7)
{
case 0: dataGridTextColumn.Header = "Mo"; break;
case 1: dataGridTextColumn.Header = "Tu"; break;
case 2: dataGridTextColumn.Header = "We"; break;
case 3: dataGridTextColumn.Header = "Th"; break;
case 4: dataGridTextColumn.Header = "Fr"; break;
case 5: dataGridTextColumn.Header = "Sa"; break;
case 6: dataGridTextColumn.Header = "Su"; break;
}
dataGridTextColumn.Binding = new Binding(string.Format("Days[{0}].NumericDay", i));
//Set BackGround property in style and use converter to set background according to HolidayType
dataGridTextColumn.CellStyle = new Style(typeof(DataGridCell));
dataGridTextColumn.CellStyle.Setters.Add(
new Setter
{
Property = DataGridCell.BackgroundProperty,
Value = new Binding(string.Format("Days[{0}]", i)) { Converter = converter }
});
}
dataGrid.Columns.Add(dataGridTextColumn);
}
}
}
Converter
public class BackGroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var day = value as Day;
if (day != null)
{
//Dont use else if Like Saturday can be a restricted holiday so gray needs to be overridden by red.
if (day.HolidayType == HolidayType.SatOrSun)
return new SolidColorBrush(Colors.Gray);
if (day.HolidayType == HolidayType.RestrictedHoliday)
return new SolidColorBrush(Colors.Red);
if (day.HolidayType == HolidayType.PublicHoilday)
return new SolidColorBrush(Colors.Blue);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Custom Types
public enum HolidayType
{
None,
SatOrSun,
PublicHoilday,
RestrictedHoliday
}
public class Day
{
public int? NumericDay { get; set; }
public HolidayType HolidayType { get; set; }
}
public class DashboardDateDetails
{
public string MonthName { get; set; }
public List<Day> Days { get; set; }
}
ViewModel
public class ViewModel
{
public ViewModel()
{
DashboardDates = new List<DashboardDateDetails>();
GenerateCalendar();
}
//This will be binded to ItemsSource
public List<DashboardDateDetails> DashboardDates { get; set; }
//Suppose these are Restricted Holidays
List<DateTime> RestrictedHolidays = new List<DateTime>{
new DateTime(2014,2,1),
new DateTime(2014,3,5),
new DateTime(2014,4,15),
new DateTime(2014,6,2),
new DateTime(2014,8,15),
new DateTime(2014,11,25),
new DateTime(2014,12,24)
};
//Suppose these are Public Holidays
List<DateTime> PublicHolidays = new List<DateTime>{
new DateTime(2014,2,1),
new DateTime(2014,3,15),
new DateTime(2014,4,19),
new DateTime(2014,6,20),
new DateTime(2014,8,11),
new DateTime(2014,11,12),
new DateTime(2014,12,25)
};
void GenerateCalendar()
{
//Lop for 12 months
for (int month = 1; month <= 12; month++)
{
//firstdate for month.This will help to get the first day of month
var firstdate = new DateTime(2014, month, 1);
//Get the first date index
int firstDateIndex = (int)firstdate.DayOfWeek;
//In DayOfWeek enum first day is Sunday but we want Monday so decrement the index
firstDateIndex--;
//Restricted holidays for this month
var restrictedHolidays = RestrictedHolidays.Where(s => s.Month == month);
//Public holidays for this month
var publicHolidays = PublicHolidays.Where(s => s.Month == month);
//Instance of DashboardDateDetails
DashboardDateDetails details = new DashboardDateDetails
{
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month),
Days = new Day[40].ToList() //Create an array of capacity 40
};
for (int j = 1; j <= DateTime.DaysInMonth(2014, month); j++)
{
int index = 0;
if (firstDateIndex < 0)
index = j - 1;
else
index = j + firstDateIndex - 1;
var day = new Day { NumericDay = j };
//is sat or sun
if (((index % 7) == 6) || ((index % 7) == 5))
day.HolidayType = HolidayType.SatOrSun;
//is restricted holiday
if (restrictedHolidays.Any(s => s.Day == index))
day.HolidayType = HolidayType.RestrictedHoliday;
//is public holiday
if (publicHolidays.Any(s => s.Day == index))
day.HolidayType = HolidayType.PublicHoilday;
details.Days[index] = day;
}
DashboardDates.Add(details);
}
}
}
Output
我希望这能帮助你给出一个想法。
关于c# - 使用 WPF Datagrid 生成一年的出勤详细信息 - 最好的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20870667/