WPF (в частности, XAML) сделан для такого рода вещей. ItemsControl
с настроенным ItemTemplate
может сделать это так элегантно, что нет абсолютно никакой причины создавать собственный элемент управления и рисовать его в коде. Чтобы показать, насколько это просто, я смоделировал простой прототип, используя в основном XAML.
Сначала несколько предварительных изменений в вашей модели памяти. Чтобы упростить вычисление высоты, я добавил свойство RelativeSize
в класс Partition
. Это именно то, на что это похоже, значение double
, которое является результатом Partition.Size / Memory.Size
. Это единственное изменение модели, которое я сделал.
Теперь, хорошие вещи:
<Window x:Class="DrawMemory.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DrawMemory"
Width="200"
Height="600"
Title="Draw Memory">
<Window.Resources>
<local:MultiplyConverter x:Key="MultiplyConverter"/>
</Window.Resources>
<Grid x:Name="Grid"
Margin="5">
<ItemsControl ItemsSource="{Binding Partitions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Position, StringFormat={}{0}k}"
Margin="5"/>
<Grid Grid.Column="1">
<Border BorderThickness="5"
BorderBrush="Black">
<Border.Height>
<MultiBinding Converter="{StaticResource MultiplyConverter}">
<Binding ElementName="Grid" Path="ActualHeight"/>
<Binding Path="RelativeSize"/>
</MultiBinding>
</Border.Height>
</Border>
<TextBlock Text="{Binding Id}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Я создал простое окно с одним ItemsControl
. Предметы, которые он использует, являются разделами, очевидно. Для каждого раздела я создаю Grid
с двумя столбцами. В первом столбце я пишу некоторый текст для позиции в памяти (я использовал StringFormat
, чтобы добавить «k»). Во втором столбце у меня есть еще один Grid
, который состоит из Border
и текста из Id
.
Единственная логика здесь - в привязке высоты. Здесь я в основном говорю: «свяжите высоту этой границы с высотой родительской сетки, умноженной на относительный размер раздела». Я создал некоторый код для многократного конвертера, но он очень прост (а не качество продукции):
public class MultiplyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return (double)values[0] * (double)values[1];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
Из-за этой привязки при изменении размера Window
высота границы будет синхронизироваться. Другими словами, это ItemsControl
всегда будет соответствовать доступному пространству. Вот как это выглядит в итоге:
Очевидно, вам нужно много полировать. Но это должно дать вам хорошее представление о том, на что способен XAML.