Как заставить высоту строки сетки занимать только необходимое ей пространство, но также ограничиваться доступным пространством в его контейнере? - PullRequest
0 голосов
/ 22 января 2019

Я хочу иметь заголовок, затем ниже ScrollViewer с ItemsControl, затем ниже этого нижнего колонтитула.Что-то вроде:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid ShowGridLines="True">
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="36"/>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">Header</TextBlock>
        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
            <ItemsControl>
                <ItemsControl.Items>
                    <TextBlock>Item 1</TextBlock>
                    <TextBlock>Item 2</TextBlock>
                    <TextBlock>Item 3</TextBlock>
                    <TextBlock>Item 4</TextBlock>
                    <TextBlock>Item 5</TextBlock>
                </ItemsControl.Items>
            </ItemsControl>
        </ScrollViewer>
        <TextBlock Grid.Row="2">Footer</TextBlock>
    </Grid>
</Window>

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

Если я изменю определение среднего ряда на Height="Auto", оно занимает точноколичество места, которое ему нужно, даже если это пространство недоступно, поэтому ScrollViewer никогда не отображает полосу прокрутки, и нижний колонтитул теряется в нижней части окна, если окно недостаточно высокое.

Как мне сделать так, чтобы, если окно было достаточно высоким, чтобы все могло поместиться, нижний колонтитул находился сразу под ItemsControl, но если окно недостаточно высокое, ScrollViewer показывает полосу прокрутки инижний колонтитул находится внизу окна?

Мне не обязательно делать это с Grid, но я не нашел другого Panel, который бы делал то, что я хочу.Например, DockPanel с заголовком, установленным на DockPanel.Dock="Top", нижним колонтитулом, установленным на DockPanel.Dock="Bottom", и ItemsControl, заполняющим остальное, ведет себя точно так же.

Некоторые другие вещи, которые я пробовал:

  • Настройка VerticalAlignment="Stretch" в нижнем колонтитуле TextBlock: без изменений.
  • Создание строки нижнего колонтитула Height="*": все еще не то, что я хочу;нижний колонтитул и ItemsControl имеют одинаковую высоту, поэтому нижний колонтитул занимает слишком много места большую часть времени, или, если вы сделаете окно очень коротким, оно уходит за нижнюю часть окна.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Спасибо ответ мами за концепцию, как это сделать, и ответ Маркуса за идею связать строки MaxHeight.

XAML:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid ShowGridLines="True">
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="36"/>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" MaxHeight="{Binding ItemsMaxHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0">Header</TextBlock>
        <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
            <ItemsControl Name="ic" SizeChanged="Ic_SizeChanged">
                <ItemsControl.Items>
                    <TextBlock>Item 1</TextBlock>
                    <TextBlock>Item 2</TextBlock>
                    <TextBlock>Item 3</TextBlock>
                    <TextBlock>Item 4</TextBlock>
                    <TextBlock>Item 5</TextBlock>
                </ItemsControl.Items>
            </ItemsControl>
        </ScrollViewer>
        <TextBlock Grid.Row="2">Footer</TextBlock>
    </Grid>
</Window>

Код:

Imports System.ComponentModel

Class MainWindow
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public ReadOnly Property ItemsMaxHeight As Double
        Get
            Dim Height = 0.0
            Dim icg = ic.ItemContainerGenerator

            For i = 0 To ic.Items.Count - 1
                Height += DirectCast(icg.ContainerFromIndex(i), FrameworkElement).ActualHeight
            Next

            Return Height + 6.0 ' 6.0 to account for the size of borders? Not sure :(
        End Get
    End Property

    Private Sub Ic_SizeChanged(sender As Object, e As SizeChangedEventArgs)
        If e.HeightChanged Then
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("ItemsMaxHeight"))
        End If
    End Sub
End Class

В этом примере XAML мне не нужно увеличивать MaxHeight на 6, но в моем реальном приложении, если я не добавлю немного больше, ScrollViewer всегда показывает полосу прокрутки, которую можно прокрутить небольшой кусочек. Не уверен, что вызывает несоответствие.

0 голосов
/ 22 января 2019

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

<Grid ShowGridLines="True" Loaded="Grid_Loaded">
    <Grid.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="36"/>
        </Style>
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*" Name="middlerow"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0">Header</TextBlock>
    <ScrollViewer Name="scv" Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <ItemsControl x:Name="items" Height="Auto" VerticalAlignment="Top">
            <ItemsControl.Items>
                <TextBlock>Item 1</TextBlock>
                <TextBlock>Item 2</TextBlock>
                <TextBlock>Item 3</TextBlock>
                <TextBlock>Item 4</TextBlock>
            </ItemsControl.Items>
        </ItemsControl>
    </ScrollViewer>
    <TextBlock Grid.Row="2">Footer</TextBlock>
</Grid>

И в коде позади:

private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        double height = 0;
        foreach (var item in items.Items)
        {
            height += (item as TextBlock).ActualHeight;
        }
        if (height < scv.ActualHeight)
        {
            middlerow.MaxHeight = height;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...