调整画布项目大小 [英] Resizing canvas items

查看:113
本文介绍了调整画布项目大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建画布,当画布本身调整大小时,调整其大小。所以我创建我自己的类继承自canvas和覆盖方法ArrangeOverride,其中我设置的位置和大小为所有在画布中定义的孩子。
一切看起来不错,但是当我调整应用程序的窗口时,项目未调整为正确的大小或位置。

I'm trying to create canvas which resizes its children when canvas itself is resized. So I create my own class which inherits from canvas and overrides method ArrangeOverride where I set positions and sizes for all children defined in canvas. Everything looks fine but when I resize window of the application, items weren't resized to correct size or position.

这是一个简化的示例,将其元素粘贴到画布的右边框:

This is simplified example, which tries to snap its elements to right border of canvas:

Xaml代码:

<Border BorderBrush="Black" BorderThickness="1" Margin="10" SnapsToDevicePixels="True">
    <l:CustomPanel>
        <Rectangle Fill="Red" />
        <Button>a</Button>
    </l:CustomPanel>
</Border>

CustomPanel:

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;
    }
}

当我改变窗口的宽度时,喜欢这张图片:

When I change width of the window, sometimes canvas looks like on this image:

然后,如果我改变窗口的高度,项目移动到正确的位置

And then, if I change height of the window, items move to correct position

我做错了什么?
我试图将SnapsToDevicePixels设置为True,它不适合我。 : - (

What am I doing wrong? I tried to set SnapsToDevicePixels to True and it doesn't work for me. :-(

推荐答案

您的自定义面板应来自 Panel Canvas 并覆盖 MeasureOverride ArrangeOverride 应该为子元素布局定义其自己的附加属性,如四个属性 RelativeX RelativeY RelativeWidth RelativeHeight 如下所示。

Your custom panel should derive from Panel instead of Canvas and override the MeasureOverride and ArrangeOverride methods. Moreover it should define its own attached properties for child element layout, like the four properties RelativeX, RelativeY, RelativeWidth and RelativeHeight shown below.

<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 类型的单个附加属性替换它们:


If you don't need the four layout properties to be independently bindable or settable by style setters etc. you could perhaps replace them by a single attached property of type 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;
    }
}

这篇关于调整画布项目大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆