我在使用自定义 UniformGrid 控件时遇到问题,该控件在应用程序启动时没有缩放其所有子控件 - 我必须稍微调整窗口大小才能正确缩放内容。
UniformGrid 用作 ItemsControl 中的 ItemsPanel。ItemsControl ItemsSource 绑定到一个viewmodel 集合,UserControls 是根据viewmodel 类型选择的。这是一个片段:
<DataTemplate DataType="{x:Type indicators:RollPitchIndicatorVM}">
<indicators:RollPitchIndicator />
</DataTemplate>
<DataTemplate DataType="{x:Type indicators:RovIllustrationIndicatorVM}">
<indicators:RovIllustrationIndicator />
</DataTemplate>
<DataTemplate DataType="{x:Type indicators:RulerIndicatorVM}">
<indicators:RulerIndicator />
</DataTemplate>
我的问题是用户控件的某些部分在应用程序启动时没有缩放。一个示例是 RovIllustrationIndicator 用户控件。它包含一个带有 Grid 的 Viewbox,其中包含一个 Image 控件和一个 ItemsControl 控件(我已经剥离了不相关的东西):
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Viewbox x:Name="RovImage" Grid.Column="1">
<Grid>
<Image x:Name="BackgroundImage" Source="{Binding Path=BackgroundImage}" Stretch="None" />
<!-- ItemsControl displaying images and polygons overlaying the Image control -->
</Grid>
</Viewbox>
</Grid>
在应用程序启动时,Viewbox 的高度和宽度都为零。但是,如果我只调整一个像素的窗口大小,则 Viewbox 会缩放到正确的大小。
问题是,如果我将顶部 ItemsControl ItemsPanel 更改为标准 UniformGrid 而不是我的自定义 WeightedUniformGrid,它在启动时可以很好地扩展。因此,WeightedUniformGrid 与 UserControls 的组合导致缩放在启动时失败。但是什么?
这是 WeightedUniformGrid 实现:
public class WeightedUniformGrid : UniformGrid
{
public static readonly DependencyProperty WeightProperty =
DependencyProperty.RegisterAttached(
"Weight",
typeof(double),
typeof(WeightedUniformGrid),
new FrameworkPropertyMetadata(
double.NaN,
FrameworkPropertyMetadataOptions.AffectsParentArrange |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public static double GetWeight(UIElement element)
{
return (double)element.GetValue(WeightProperty);
}
public static void SetWeight(UIElement element, double value)
{
element.SetValue(WeightProperty, value);
}
public static readonly DependencyProperty SortDirectionProperty =
DependencyProperty.RegisterAttached(
nameof(SortDirection),
typeof(Orientation),
typeof(WeightedUniformGrid),
new FrameworkPropertyMetadata(
Orientation.Horizontal,
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure));
public Orientation SortDirection
{
get { return (Orientation)GetValue(SortDirectionProperty); }
set { SetValue(SortDirectionProperty, value); }
}
protected override Size MeasureOverride(Size constraint)
{
var size = base.MeasureOverride(constraint);
if (Columns > 0)
{
double elementsPerColumn = Math.Ceiling((double)Children.Count / Columns);
double elementWidth = size.Width / Columns;
double unweightedElementHeight = size.Height / elementsPerColumn;
for (int i = 0; i < Children.Count; ++i)
{
var child = Children[i];
int columnNumber = (int)Math.Floor(i / elementsPerColumn);
double weight = GetWeight(child);
if (double.IsNaN(weight)) { weight = 100; }
double weightedElementHeight = unweightedElementHeight * weight / 100;
child.Measure(new Size(elementWidth, weightedElementHeight));
}
}
else if (Rows > 0)
{
double elementsPerRow = Math.Ceiling((double)Children.Count / Rows);
double elementHeight = size.Height / Rows;
double unweightedElementWidth = size.Width / elementsPerRow;
for (int i = 0; i < Children.Count; ++i)
{
var child = Children[i];
int rowNumber = (int)Math.Floor(i / elementsPerRow);
double weight = GetWeight(child);
if (double.IsNaN(weight)) { weight = 100; }
double weightedElementWidth = unweightedElementWidth * weight / 100;
child.Measure(new Size(weightedElementWidth, elementHeight));
}
}
return size;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
var size = base.ArrangeOverride(arrangeSize);
if (Columns > 0)
{
int elementsPerColumn = (int)Math.Ceiling((double)Children.Count / Columns);
double elementWidth = size.Width / Columns;
double unweightedElementHeight = size.Height / elementsPerColumn;
double[] accumulatedHeightPerColumn = new double[Columns];
for (int i = 0; i < Children.Count; ++i)
{
var child = Children[i];
int columnNumber;
if (SortDirection == Orientation.Vertical) // Vertical orientation
{
columnNumber = i / elementsPerColumn;
}
else // Horizontal orientation
{
columnNumber = i % Columns;
}
double weight = GetWeight(child);
if (double.IsNaN(weight)) { weight = 100; }
double weightedElementHeight = unweightedElementHeight * weight / 100;
child.Arrange(new Rect(new Point(columnNumber * elementWidth, accumulatedHeightPerColumn[columnNumber]),
new Point((columnNumber + 1) * elementWidth, accumulatedHeightPerColumn[columnNumber] + weightedElementHeight)));
accumulatedHeightPerColumn[columnNumber] += weightedElementHeight;
}
}
else if (Rows > 0)
{
int elementsPerRow = (int)Math.Ceiling((double)Children.Count / Rows);
double elementHeight = size.Height / Rows;
double unweightedElementWidth = size.Width / elementsPerRow;
double[] accumulatedWidthPerRow = new double[Rows];
for (int i = 0; i < Children.Count; ++i)
{
var child = Children[i];
int rowNumber;
if (SortDirection == Orientation.Vertical) // Vertical orientation
{
rowNumber = i % Rows;
}
else // Horizontal orientation
{
rowNumber = i / elementsPerRow;
}
double weight = GetWeight(child);
if (double.IsNaN(weight)) { weight = 100; }
double weightedElementWidth = unweightedElementWidth * weight / 100;
child.Arrange(new Rect(new Point(accumulatedWidthPerRow[rowNumber], rowNumber * elementHeight),
new Point(accumulatedWidthPerRow[rowNumber] + weightedElementWidth, (rowNumber + 1) * elementHeight)));
accumulatedWidthPerRow[rowNumber] += weightedElementWidth;
}
}
return size;
}
}