ListBox Silverlight 2 с пользовательской панелью не будет соответствовать размеру от ArrangeOverride - PullRequest
1 голос
/ 07 февраля 2009

Если я использую пользовательскую панель для размещения своих ListBoxItems, ListBox не будет учитывать их объединенную высоту (хотя она действительно учитывает их объединенную ширину) - даже когда мой ArrangeOverride возвращает размер, который окружает все элементы.

Установка высоты ListBox явно заставляет все работать, но я хочу, чтобы это сработало само собой!

Кто-нибудь видел это раньше?

Спасибо

Обновление: В приведенном ниже примере ListBox использует настраиваемую панель, которая размещает статьи по вертикали в соответствии со свойством Row и возвращает размер, достаточно большой, чтобы охватить их все. Но если я не установлю высоту для ListBox, он рухнет!

<UserControl x:Class="SilverlightApplication1.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="clr-namespace:SilverlightApplication1">
<UserControl.Resources>
    <DataTemplate x:Key="ArticleTemplate">
        <TextBlock Text="{Binding Title}" />
    </DataTemplate>
</UserControl.Resources>
<ListBox Height="200"
        Background="AntiqueWhite"
        ItemTemplate="{StaticResource ArticleTemplate}"
        ItemsSource="{Binding}" VerticalAlignment="Top"
        Margin="0,0,0,0">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <local:MyPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>
</UserControl>

Вот панель:

public class MyPanel : Panel
{
    protected override Size ArrangeOverride(Size arrangeSize)
    {
        double width = 0, height = 0;
        foreach (UIElement child in this.Children)
        {
            var article = (Article)((ContentControl)child).DataContext;
            var y = child.DesiredSize.Height * article.Row;
            var location = new Point(0, y);
            var rect = new Rect(location, child.DesiredSize);
            child.Arrange(rect);
            width = Math.Max(width, child.DesiredSize.Width);
            height = Math.Max(height, y + child.DesiredSize.Height);
        }

        return new Size(width, height);
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        foreach (UIElement child in this.Children)
        {
            if (child != null)
            {
                child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
            }
        }

        return new Size();
    }
}

И класс домена:

public class Article
{
    private readonly int row;
    private readonly string title;

    public Article(string title, int row)
    {
        this.title = title;
        this.row = row;
    }

    public int Row { get { return this.row; } }

    public string Title { get { return this.title; } }
}

Ответы [ 2 ]

1 голос
/ 09 февраля 2009

Не забывайте, что ListBoxes содержат ScrollViewers. ScrollViewer, вероятно, видит рост своих детей и думает «как хорошо, я справлюсь с этим», а затем устанавливает свой собственный размер.

Попробуйте установить

ScrollViewer.VerticalScrollBarVisibility = "Hidden"

или

ScrollViewer.VerticalScrollBarVisibility = "Disabled"

в вашем ListBox и посмотрите, что произойдет.

1 голос
/ 08 февраля 2009

Мне не удалось воспроизвести проблему, которую вы описали. Не могли бы вы предоставить пример кода / xaml, чтобы я мог посмотреть?

UPDATE:

Я считаю, что проблема в том, что вы возвращаете (0,0) как DesiredSize панели из MeasureOverride. Вы, вероятно, хотите сделать что-то вроде:

    protected override Size MeasureOverride(Size availableSize)
    {
        double width = 0;
        double height = 0;
        foreach (UIElement child in this.Children)
        {
            if (child != null)
            {
                child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                width = Math.Max(width, child.DesiredSize.Width);
                height = Math.Max(height, child.DesiredSize.Height);
            }
        }

        return new Size(width, height);
    }

Фактическая логика калибровки может отличаться в зависимости от ваших требований.

То, что происходит в вашем коде, заключается в том, что, возвращая (0,0) из MeasureOverride, ваша Panel, по сути, «запрашивает» у своего родителя этот объем пространства, который будет зарезервирован для него. Поэтому, когда дело доходит до фазы Arrange цикла макета, finalSize, переданный в ArrangeOverride, очень мал (0 по крайней мере в одном измерении). В этом можно убедиться, установив точку останова в ArrangeOverride, а затем изучив параметр finalSize. Чтобы ваш код работал корректно с системой макетов, вам нужно вернуть из MeasureOverride минимальный объем пространства, необходимого вашей Panel для хранения его дочерних элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...