DockPanel ItemsControl заполнение последней строки - PullRequest
0 голосов
/ 04 октября 2010

У меня есть док-панель, которую я динамически заполняю, используя ItemsControl для заполнения панели.Для док-панели нужен последний дочерний элемент из списка itemscontrol, чтобы заполнить остальную часть панели, но, похоже, этого не произойдет, если я заполню ее таким образом ... что я могу сделать, чтобы этот последний элемент расширился?

Фрагмент того, как я его настроил: (обратите внимание, я установил синий фон док-панели, чтобы я мог отличить заполненные пользовательские элементы управления от фона панели)

        <DockPanel Background="Blue" LastChildFill="True" Margin="0">
        <ItemsControl ItemsSource="{Binding Requirements}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:TMGrid2View Baseline="{Binding}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DockPanel>

Мойтекущая гипотеза о том, что происходит, заключается в том, что дочерняя заливка применяется к элементу управления вместо дочерних элементов, заполненных в элементе управления.В прошлом я использовал сеттеры, чтобы указать, что дочерний элемент должен пристыковаться, например, к боковой части панели ... но, похоже, нет опции дочернего сеттера, чтобы заставить его расширяться ...

Ответы [ 4 ]

6 голосов
/ 04 октября 2010

Не помещайте ItemsControl в DockPanel; положить DockPanel в ItemsControl. Используйте ItemsPanelTemplate, чтобы ItemsControl выложил свои предметы в DockPanel.

Используйте ItemContainerStyle, чтобы установить свойство DockPanel.Dock для контейнеров элементов (которое для ItemsControl будет ContentPresenter с).

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <ItemsControl Margin="5">
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <DockPanel LastChildFill="True"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
      <Style TargetType="ContentPresenter">
        <Setter Property="DockPanel.Dock" Value="Top"/>
      </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <TextBlock Background="Lavender" Margin="1" Padding="5" Text="{Binding}"/>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
    <sys:String>Athos</sys:String>
    <sys:String>Porthos</sys:String>
    <sys:String>Aramis</sys:String>
    <sys:String>D'Artagnan</sys:String>
  </ItemsControl>
</Page>
3 голосов
/ 04 октября 2010

Происходит следующее: ваша DockPanel заполнена ItemsControl. Все идет нормально. Тем не менее, ItemsControl внутри использует StackPanel, который не может заполнить по вертикали (по горизонтали, если установлено в Orientation = "Horizontal".

РЕДАКТИРОВАТЬ: Чтобы объяснить, синий фон ... фон ItemsControl по умолчанию установлен на ноль.

Вы знаете, сколько предметов в коллекции?

РЕДАКТИРОВАТЬ 2: Что нужно сделать, когда это динамическая коллекция, добавить следующее:

<ItemsControl ...>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="1"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <!-- rest of ItemsControl properties -->
</ItemsControl>

Uniform Grid назначает равное количество пространства каждой ячейке как по горизонтали, так и по вертикали, а ItemsPanel заменяет стандартную StackPanel для позиционирования.

РЕДАКТИРОВАТЬ3: Работа с элементами неравной высоты ... пользовательская панель:

public class CustomPanel : StackPanel
{
    protected override Size ArrangeOverride(Size finalSize)
    {
        var childUIElements = Children.OfType<UIElement>().ToList();
        foreach (var child in childUIElements)
        {
            child.Measure(finalSize);
        }
        double remainingHeight = finalSize.Height - childUIElements.Sum(c => c.DesiredSize.Height);
        if(remainingHeight <= 0)
            return base.ArrangeOverride(finalSize);

        double yOffset = 0;
        foreach (var child in childUIElements)
        {
            double height = child.DesiredSize.Height + remainingHeight/childUIElements.Count;
            child.Arrange(new Rect(0,yOffset,finalSize.Width,height));
            yOffset += height;
        }
        return finalSize;
    }
}

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

ПОСЛЕДНИЕ РЕДАКТИРОВАТЬ (я думаю :-)) Вам нужно поместить эту пользовательскую панель внутри ItemsPanelTemplate вместо UniformGrid, который я предлагал ранее.

0 голосов
/ 04 октября 2010

Я выброшу не элегантное решение:

в представлении модели, разделите привязку списка на список, содержащий все элементы, кроме последнего, а затем последний элемент отдельно.Затем используйте элемент управления для списка и вручную добавьте дополнительную запись, ссылающуюся на последний элемент.Я бы не хотел этого делать, так что, надеюсь, есть лучший способ.

0 голосов
/ 04 октября 2010

Вы установили для свойства DockPanel.Dock желаемое значение?

...