假设我有课:
public class YearOfLife
{
public int YearAbsolute;
public int YearRelative;
public List<Week> Weeks = new List<Week>();
}
public class Week
{
public string Tooltip;
public WeekType WeekType;
public DateTime Start;
public DateTime End;
}
public enum WeekType
{
Empty,
Passed,
Future,
PossibleFuture
}
假设我有一个生成数据的代码:
List<YearOfLife> Life = new List<YearOfLife>()
public void ReGenerateLife()
{
Life.Clear();
var yearStart = new DateTime(DayBirth.Year, 1, 1, 0, 0, 0);
yearStart = yearStart.AddDays(8 - (int)yearStart.DayOfWeek);
for (var i = yearStart; i <= DayDeath2; i = i.AddYears(1))
{
var tmpYear = new YearOfLife();
tmpYear.YearAbsolute = i.Year;
tmpYear.YearRelative = i.Year - DayBirth.Year;
Life.Add(tmpYear);
}
var currDate = yearStart;
while (currDate <= DayDeath2)
{
var lstItem = Life.Where(a => a.YearAbsolute == currDate.Year).ToList()[0];
var week = new Week();
week.Start = currDate;
week.End = currDate.AddDays(6);
if (currDate < DayBirth)
{
week.WeekType = WeekType.Empty;
}
else if (currDate <= DateTime.Today)
{
week.WeekType = WeekType.Passed;
}
else if (currDate <= DayDeath)
{
week.WeekType = WeekType.Future;
}
else if (currDate <= DayDeath2)
{
week.WeekType = WeekType.PossibleFuture;
}
lstItem.Weeks.Add(week);
currDate = currDate.AddDays(7);
}
}
XAML中还有一个workshop解决了部分问题:
<Window.Resources>
<Style TargetType="ColumnDefinition" x:Key="lifecol" >
<Setter Property="SharedSizeGroup" Value="A"/>
<Setter Property="Width" Value="30"/>
</Style>
<Style TargetType="RowDefinition" x:Key="liferow" >
<Setter Property="SharedSizeGroup" Value="A"/>
<Setter Property="Height" Value="20"/>
</Style>
</Window.Resources>
<ListBox Grid.Row="2" Name="lifeControlWrapper" Background="AliceBlue" ItemsSource="{Binding Life}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding YearsAbsolute}" VerticalAlignment="Center" Grid.Column="0"/>
<TextBlock Text="{Binding YearsRelative}" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Column="1"/>
<Grid Grid.Column="2" HorizontalAlignment="Stretch" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Style="{StaticResource lifecol}"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Style="{StaticResource liferow}"/>
</Grid.RowDefinitions>
<Button Name="brnFirst" Width="auto" Margin="2" Grid.Column="0" Height="{Binding ElementName=brnFirst, Path=Width}"></Button>
<Button Width="auto" Margin="2" Grid.Column="1"></Button>
</Grid>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
同时,我希望能够与窗口一起缩放,并且单元格将同时保持方形(部分实现)
问题:
- 如何根据
Life每个“周”的按钮输出中生成的数据来执行此操作?不要为一年中的每个星期写一个按钮?(行)以便您可以通过绑定手动显示它? - 如何每 5 个单元格缩进一次?(垂直和水平)
- 如何根据 WeekType 更改按钮颜色?
- 如何根据某些框架中的窗口大小自动更改年数的字体?
……
简而言之,鉴于我想在使用 WPF 方面正确地完成所有工作,而不仅仅是这样做,如何实现图片中的结果。
我们需要代码+解释为什么这样做/为什么这种方法是正确的。没有狂热的咀嚼。但仅限于主要思想。


在您的布局中,基本尺寸是日历单元格的尺寸,标题的尺寸取决于它。由于我想不出一种优雅的方法将测量单元格大小的结果从位于模板中的面板转发到
ItemsControl外部,我们将做相反的事情 - 我们将从外部计算单元格大小并将其传递给日历本身的面板及其标题面板。奖励 - 您可以为日历及其标题使用相同的面板。因此,让我们将一个无害的放入窗口的根 Grid 中,
ContentControl并使用转换器将Tag单元格大小写入其大小。我对转换器有这样的空白:
它实现
MarkupExtension了 ,因此在标记中使用它更方便一些 - 无需创建额外的资源。所以转换器:我们将需要一些常量,比如日历中的列数和其他东西,也许你会在 VM 中拥有它们,但我也使用了一堆标记扩展:
现在我们写:
现在我们有了单元格大小,我们可以将其用作日历单元格(正方形)的高度和宽度,以及行标题的高度和列标题的宽度
现在我们正在编写一个面板,它将其元素放置在具有大小缩进的相同大小的单元格中:
测试。虚拟机:
添加到根网格:
我们推出:
现在是头条新闻。我从这里得到了这个想法,写了一个这样的类来在视图端显示标题:
这样的转换器将为我们生成一个列表
HeaderItem:我们在根内部使用
Grid:Я привязал размер шрифта заголовка к размеру ячейки, это не самое гибкое решение, но вы можете написать конвертер, который будет использовать некий коэффициент масштаба, а также принимать максимальное и минимальное значение размера шрифта.
Тут вы уже можете заметить, что изменение размеров окна начинает притормаживать (если в настройках Windows включена опция "Отображать содержимое окна при перетаскивании), т. к. на каждый пиксель (даже чаще) пройденный мышью происходит пересчет размеров ячейки, потом отрисовка заголовков, при этом место под календарь тоже меняется, меняется размер ячейки и т. д. пока не будут рассчитаны окончательные размеры.
Я написал немного кода для перехвата сообщений и выставления простой текстовой заглушки вместо контента окна:
您可以改为在窗口中公开一个 DP,并在标记中对其进行触发器并输出一些更具吸引力的存根。
未完待续...
GitHub上项目的存储库:WpfSplitGrid