Я придумал другой подход, чем тот, который вы предлагаете.Это упрощено, и я сделал предположение или два, но давайте попробуем.
Вместо того, чтобы использовать сетку и сопоставлять дни в сетке, давайте используем WrapPanel и просто помещаем в нее дочерние элементы, каждый из которых представляетдень.
В вашем App.xaml.cs вы можете поместить некоторый код, который создаст объект Day
.
public class Day
{
public DateTime Date { get; set; }
public List<Appointment> Appointments { get; set; }
}
public partial class App : Application
{
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
var daysCollection = new List<Day>();
for (int i = 1; i <= 30; i++)
{
daysCollection.Add(new Day
{
// arbitrary sample data
Date = new DateTime(2011, 04, i),
Appointments =
new List<Appointment>
{
new Appointment
{
Date = new DateTime(2011, 04, i),
Description = "Some descriptive text"
}
}
});
}
this.Properties.Add("DaysCollection", daysCollection );
}
}
Теперь у нас есть набор дней.Встречи не важны для этой части образца.
Теперь мы создаем простой календарь UserControl и привязываем его к CalendarViewModel.
<UserControl x:Class="DaysCalendarBinding.Views.Calendar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Height="210" Width="210">
<WrapPanel x:Name="wrapPanel" Orientation="Horizontal"
ItemHeight="30" ItemWidth="30"
Loaded="wrapPanel_Loaded">
</WrapPanel>
</UserControl>
ViewModel
public class CalendarViewModel
{
public CalendarViewModel()
{
}
public CalendarViewModel(IEnumerable<Day> inputDays)
{
// determine first day of the month passed in
var firstDate =
(from day in inputDays
orderby day.Date.Day
select day.Date).First();
var todayIs = firstDate.DayOfWeek;
var valueOfToday = (int) todayIs;
// create this many blank day children
DaysInMonth = new List<Day>();
for (int i = valueOfToday; i > 0; i--)
{
// the start of some cheeze. I know. It's a sample.
DaysInMonth.Add(new Day { Date = new DateTime(1,1,1) });
}
// add the rest ofthe days in to the collection
foreach(var day in inputDays)
{
DaysInMonth.Add(day);
}
}
public List<Day> DaysInMonth { get; private set; }
}
С помощью обработчика событий для загрузки wrapPanel
private void wrapPanel_Loaded(object sender, RoutedEventArgs e)
{
foreach (var day in ((CalendarViewModel)DataContext).DaysInMonth)
{
wrapPanel.Children.Add(
new DayView {
DataContext = new DayViewModel(day) });
}
}
Теперь мы создаем элемент управления DayViewModel и DayView, который мы создаем и добавляем в WrapPanel.
<UserControl x:Class="DaysCalendarBinding.Views.DayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="30">
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel Height="30" Width="30" Background="AliceBlue">
<TextBlock FontSize="7" Text="{Binding DayDate}"/>
</StackPanel>
</Border> </UserControl>
ViewModel
public class DayViewModel
{
private Day innerDay;
public DayViewModel() {}
public DayViewModel(Day day)
{
innerDay = day;
}
public string DayDate
{
get
{
// I know this is a cheesy approach. It's a sample. :)
if (innerDay.Date.Year != 1)
// this only intended to demonstrate some content
return innerDay.Date.DayOfWeek.ToString().Remove(3) +
" " + innerDay.Date.Day;
return string.Empty;
}
}
}
Теперь, наконец, наше главное окно, где мы добавляем элемент управления Calendar, добавляем CalendarViewModel и, надеюсь, когда мы нажимаем F5, оно появляется для вас.:)
<Window x:Class="DaysCalendarBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Views="clr-namespace:DaysCalendarBinding.Views" Title="Calendar Demo" Height="350" Width="525">
<Grid>
<Views:Calendar x:Name="calendarControl"></Views:Calendar>
</Grid>
</Window>
Кодовый код в MainWindow.xaml.cs
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
calendarControl.DataContext =
new CalendarViewModel((IEnumerable<Day>)Application
.Current
.Properties["DaysCollection"]);
}
Возможно, я допустил одну или две ошибки, перенеся это сюда из моего решения.Но я надеюсь, что это передает идею.Вот как это выглядит для меня:
Календарь марта
Календарь апреля
* 1043Теперь наступает момент, когда все это складывается так, чтобы оно работало на вас.Это просто демонстрирует технику.Представить значимый контроль не должно быть так сложно.
Приветствия.