【问题标题】:Items Measuring return weird DesiredSize, Silverlight测量返回奇怪的项目 DesiredSize、Silverlight
【发布时间】:2013-06-24 09:05:44
【问题描述】:

我需要在列表框和面板之间实现一些东西。它必须有没有自己风格的可绑定项目源。所以我决定从FrameworkElement派生。 我试图在我的控件后面的代码中添加新按钮,并在更改 ItemsSource 属性时调用 InvalidateMeasure。在 MeasureOverride 方法中,我运行 itemssource 集合并使用 availableSize 作为每个项目的参数调用 Measure。但结果我得到了itemssouce内控件的奇怪DesiredSize(在我的情况下是按钮) - 16高度和0宽度。这是我的代码:

    // part from usercontrol's code behind  
    public MainPage()
    {
        InitializeComponent();

        dash.ItemsSource.Add(new Button { Content = "button 1 content", Padding = new Thickness(10) });
        dash.ItemsSource.Add(new Button { Content = "button 2 content", Padding = new Thickness(10) });
    }

    //part from my control
    protected override Size MeasureOverride(Size availableSize)
    {
        var desiredSize = new Size();
        foreach (UIElement item in ItemsSource)
        {
            item.Measure(availableSize);
            desiredSize.Height += item.DesiredSize.Height;
            desiredSize.Width += item.DesiredSize.Width;
        }
        return desiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {           
        double x = 25, y = 25;
        foreach (FrameworkElement item in ItemsSource)
        {
            item.Arrange(new Rect(x, y, item.DesiredSize.Width, item.DesiredSize.Height));
        }

        return base.ArrangeOverride(finalSize);
    }

我尝试手动设置项目的高度和宽度,但没有帮助。甚至尝试使用 new Size(double.PositiveInfinity,double.PositiveInfinity); 第一次调用 Measure 两次而且无论如何按钮都不想出现在用户控件上。

请帮我确定我做错了什么!

【问题讨论】:

  • 你的方法是完全错误的。您通常会设置ItemsControlListBoxItemsPanelItemContainerStyleItemTemplate 属性。请告诉我们这些项目应如何排列,因为当前您正试图在 x=25/y=25 处将它们全部叠放,这似乎没有意义。
  • 我只是尝试将项目添加到我的控件并显示它们。我不在乎他们必须在哪里。你有一个观点,但结果我会得到基于 ItemsControl 或任何其他控件不能(也不应该)的复杂事物。顺便说一句,我发现了问题。我错过了非常重要的东西——视觉树。我没有向视觉树添加新按钮,它们没有父级。我试图查看其他面板的工作方式。他们使用具有内部构造函数的 UIElementCollection。我想那里发生了一些“魔术”...... Silverlight 在 wpf 之后非常令人沮丧......
  • 你肯定会让你的控件的用户感到困惑,因为它的“项目”只能是控件(或者准确地说是 UIElements)。但是,ItemsSource 属性意义上的项目可以是任何类型的对象。您至少应该创建一个派生面板,并将 UIElements 添加到其Children 集合中。如果您想详细说明您实际上想要如何安排孩子,您可能会在这里得到一个有用的解决方案。
  • Panel中的备注:For scenarios that require application layout that is not possible using any of the predefined Panel elements, custom layout behaviors can be achieved by inheriting from Panel and overriding the default measure and arrange behavior by using the MeasureOverride and ArrangeOverride methods

标签: c# .net silverlight


【解决方案1】:

您正在寻找的是派生面板。由于您没有真正解释您想要的布局应该是什么样子,以下示例通过将每个子项放置在前一个子项的右下角来“对角”排列面板的子项。此外,它忽略任何水平或垂直对齐设置。您可以像使用任何其他 Panel 一样使用它,并在 XAML 或代码中添加子代。

public class MyPanel : Panel
{
    protected override Size MeasureOverride(Size availableSize)
    {
        var infiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);

        foreach (UIElement child in Children)
        {
            child.Measure(infiniteSize); // allow unconstrained child size
        }

        return new Size(); // consume as less size as possible
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        var position = new Point();

        foreach (UIElement child in Children)
        {
            var size = child.DesiredSize;
            child.Arrange(new Rect(position, size));
            position.X += size.Width;
            position.Y += size.Height;
        }

        return new Size(position.X, position.Y);
    }
}

【讨论】:

  • 谢谢,克莱门斯!我做了类似的事情,它正在工作。也许有点难看,但工作......
  • 如果您需要排列子元素,请使用面板,因为这正是它的用途。除非您真的知道自己在做什么,否则其他任何事情都会令人困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 2020-10-01
  • 2020-12-17
  • 1970-01-01
相关资源
最近更新 更多