我正在尝试创建画布,当画布本身被调整大小时,该画布将调整其子对象的大小。因此,我创建了一个自己的类,该类继承自canvas,并覆盖了ArrangeOverride方法,在其中我为画布中定义的所有子级设置位置和大小。一切看起来都很好,但是当我调整应用程序窗口的大小时,项目的大小并未调整为正确的大小或位置。
这是简化的示例,尝试将其元素对齐到画布的右边界:
Xaml代码:
<Border BorderBrush="Black" BorderThickness="1" Margin="10" SnapsToDevicePixels="True">
<l:CustomPanel>
<Rectangle Fill="Red" />
<Button>a</Button>
</l:CustomPanel>
</Border>
CustomPanel:
public class CustomPanel : Canvas
{
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
var ret = base.ArrangeOverride(arrangeSize);
var top = 0;
foreach(UIElement child in Children)
{
Canvas.SetLeft(child, arrangeSize.Width - 20.0);
child.SetValue(WidthProperty, arrangeSize.Width - Canvas.GetLeft(child));
Canvas.SetTop(child, top);
child.SetValue(HeightProperty, 20.0);
top += 30;
}
return ret;
}
}
当我更改窗口的宽度时,有时画布在此图像上看起来像:
然后,如果我更改窗口的高度,则项目将移动到正确的位置
我究竟做错了什么?我试图将SnapsToDevicePixels设置为True,但对我来说不起作用。:-(
您的自定义面板应源自Panel
而不是Canvas
和覆盖MeasureOverride
andArrangeOverride
方法。此外,应该定义它自己的附加属性为子元素的布局,如四个属性RelativeX
,RelativeY
,RelativeWidth
和RelativeHeight
如下所示。
它将在XAML中像这样使用:
<local:RelativeLayoutPanel>
<Rectangle Fill="Red"
local:RelativeLayoutPanel.RelativeX="0.2"
local:RelativeLayoutPanel.RelativeY="0.1"
local:RelativeLayoutPanel.RelativeWidth="0.6"
local:RelativeLayoutPanel.RelativeHeight="0.8"/>
</local:RelativeLayoutPanel>
这是实现:
public class RelativeLayoutPanel: Panel
{
public static readonly DependencyProperty RelativeXProperty = DependencyProperty.RegisterAttached(
"RelativeX", typeof(double), typeof(RelativeLayoutPanel),
new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
public static readonly DependencyProperty RelativeYProperty = DependencyProperty.RegisterAttached(
"RelativeY", typeof(double), typeof(RelativeLayoutPanel),
new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
public static readonly DependencyProperty RelativeWidthProperty = DependencyProperty.RegisterAttached(
"RelativeWidth", typeof(double), typeof(RelativeLayoutPanel),
new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
public static readonly DependencyProperty RelativeHeightProperty = DependencyProperty.RegisterAttached(
"RelativeHeight", typeof(double), typeof(RelativeLayoutPanel),
new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
public static double GetRelativeX(UIElement element)
{
return (double)element.GetValue(RelativeXProperty);
}
public static void SetRelativeX(UIElement element, double value)
{
element.SetValue(RelativeXProperty, value);
}
public static double GetRelativeY(UIElement element)
{
return (double)element.GetValue(RelativeYProperty);
}
public static void SetRelativeY(UIElement element, double value)
{
element.SetValue(RelativeYProperty, value);
}
public static double GetRelativeWidth(UIElement element)
{
return (double)element.GetValue(RelativeWidthProperty);
}
public static void SetRelativeWidth(UIElement element, double value)
{
element.SetValue(RelativeWidthProperty, value);
}
public static double GetRelativeHeight(UIElement element)
{
return (double)element.GetValue(RelativeHeightProperty);
}
public static void SetRelativeHeight(UIElement element, double value)
{
element.SetValue(RelativeHeightProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
foreach (UIElement element in InternalChildren)
{
element.Measure(availableSize);
}
return new Size();
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement element in InternalChildren)
{
element.Arrange(new Rect(
GetRelativeX(element) * finalSize.Width,
GetRelativeY(element) * finalSize.Height,
GetRelativeWidth(element) * finalSize.Width,
GetRelativeHeight(element) * finalSize.Height));
}
return finalSize;
}
}
如果您不需要四个布局属性可以由样式设置程序等独立绑定或设置,则可以将其替换为一个类型的附加属性Rect
:
<local:RelativeLayoutPanel>
<Rectangle Fill="Red" local:RelativeLayoutPanel.RelativeRect="0.2,0.1,0.6,0.8"/>
</local:RelativeLayoutPanel>
使用以下更短的实现:
public class RelativeLayoutPanel: Panel
{
public static readonly DependencyProperty RelativeRectProperty = DependencyProperty.RegisterAttached(
"RelativeRect", typeof(Rect), typeof(RelativeLayoutPanel),
new FrameworkPropertyMetadata(new Rect(), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
public static Rect GetRelativeRect(UIElement element)
{
return (Rect)element.GetValue(RelativeRectProperty);
}
public static void SetRelativeRect(UIElement element, Rect value)
{
element.SetValue(RelativeRectProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
foreach (UIElement element in InternalChildren)
{
element.Measure(availableSize);
}
return new Size();
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement element in InternalChildren)
{
var rect = GetRelativeRect(element);
element.Arrange(new Rect(
rect.X * finalSize.Width,
rect.Y * finalSize.Height,
rect.Width * finalSize.Width,
rect.Height * finalSize.Height));
}
return finalSize;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句