【问题标题】:Multipass MeasureOverride() do recompute child sizeMultipass MeasureOverride() 重新计算子大小
【发布时间】:2014-07-02 13:50:26
【问题描述】:

我有一个带有自定义控件的自定义面板,它应该像 RibbonButton 一样调整大小,即随着可用大小的变化,我应该删除/添加标题、调整内部图片的大小等...

进一步自定义控件是lookless控件,即UI/Template在样式中定义,我使用触发器来更新模板元素。

我通过使用继承的附加属性(我的意思是 UI 继承,如 DataContext)将面板的大小设置传达给各个控件

当我在面板中执行多次传递MeasureOverride() 时,当我调用child.Measure() 时,就好像我的项目总是相同尺寸! 尽管我更改了继承的附加属性(并且它确实在控制内部更新!) 要清楚我的内部控件不会调整大小,但是当我更改继承的属性时,它们会更改其 UI 模板(更改为较小的版本)

知道如何成功实现 RibbonButon 和 RibbonGroupPanel 类行为吗?

【问题讨论】:

  • 贴出你试过的代码

标签: wpf wpf-4.0


【解决方案1】:

我可能没有在我的继承财产上设置正确的元数据选项! 当我设法让它工作时调整它们!

为了清楚起见,我将在下面发布我可以写的最简单的示例(我以前没有这样做,因为即使是最简单的示例也很长!!)

Size123Control.cs

public class Size123Control : Control
{
    static Size123Control()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Size123Control), new FrameworkPropertyMetadata(typeof(Size123Control)));
    }
}

Size123Panel.cs

public class Size123Panel : Panel
{
    public static int GetSize123(DependencyObject obj) { return (int)obj.GetValue(Size123Property); }

    public static void SetSize123(DependencyObject obj, int value) { obj.SetValue(Size123Property, value); }

    public static readonly DependencyProperty Size123Property = DependencyProperty.RegisterAttached(
        "Size123", typeof(int), typeof(Size123Panel), 
        new FrameworkPropertyMetadata(3,
            FrameworkPropertyMetadataOptions.Inherits
            | FrameworkPropertyMetadataOptions.AffectsMeasure
            | FrameworkPropertyMetadataOptions.AffectsParentMeasure
            | FrameworkPropertyMetadataOptions.AffectsArrange
            | FrameworkPropertyMetadataOptions.AffectsParentArrange
            ));

    protected override Size ArrangeOverride(Size finalSize)
    {
        double hTot = 0, h = 0, x = 0, xMax = 0;
        foreach (UIElement child in Children)
        {
            var cs = child.DesiredSize;
            if (x > 0 && x + cs.Width > finalSize.Width)
            {
                hTot += h;
                x = 0;
                h = cs.Height;
            }
            else
            {
                if (cs.Height > h)
                    h = cs.Height;
            }
            child.Arrange(new Rect(new Point(x, hTot), cs));
            x += cs.Width;
            if (x > xMax)
                xMax = x;
        }
        return new Size(xMax, hTot + h);
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        Func<Size> measure = () =>
        {
            double hTot = 0, h = 0, x = 0, xMax = 0;
            foreach (UIElement child in Children)
            {
                child.Measure(availableSize);
                var cs = child.DesiredSize;

                if (x > 0 && x + cs.Width > availableSize.Width)
                {
                    hTot += h;
                    x = 0;
                    h = cs.Height;
                }
                else
                {
                    if (cs.Height > h)
                        h = cs.Height;
                }
                x += cs.Width;
                if (x > xMax)
                    xMax = x;
            }
            return new Size(xMax, hTot + h);
        };

        SetSize123(this, 3);
        var s1 = measure();
        if (s1.Width <= availableSize.Width && s1.Height <= availableSize.Height)
            return s1;

        SetSize123(this, 2);
        var s2 = measure();
        if (s2.Width <= availableSize.Width && s2.Height <= availableSize.Height)
            return s2;

        SetSize123(this, 1);
        var s3 = measure();

        return s3;
    }
}

generic.xaml

<Style TargetType="{x:Type local:Size123Control}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Size123Control}">
                <Border x:Name="MAIN" Width="48" Height="48" Background="Red" BorderThickness="1" BorderBrush="LightGray"/>
                <ControlTemplate.Triggers>
                    <Trigger Property="local:Size123Panel.Size123" Value="2">
                        <Setter TargetName="MAIN" Property="Background" Value="Green"/>
                        <Setter TargetName="MAIN" Property="Width" Value="32"/>
                        <Setter TargetName="MAIN" Property="Height" Value="32"/>
                    </Trigger>
                    <Trigger Property="local:Size123Panel.Size123" Value="1">
                        <Setter TargetName="MAIN" Property="Background" Value="Blue"/>
                        <Setter TargetName="MAIN" Property="Width" Value="16"/>
                        <Setter TargetName="MAIN" Property="Height" Value="16"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ma​​in.xaml

<local:Size123Panel>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
    <local:Size123Control/>
</local:Size123Panel>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2014-06-20
    • 2012-12-22
    • 2018-04-27
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多