Как закрепить один элемент управления под другим в Silverlight? - PullRequest
3 голосов
/ 11 мая 2009

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

Пока что мой специальный ряд является частью ScrollViewer вместе с RowsPresenter. И докладчик, и специальная строка находятся в строках с автоматическими размерами Grid в пределах ScrollViewer, а ScrollViewer - в строке сетки звездного размера, так что полоса прокрутки будет появляться, когда в ней заканчивается свободное место. Как я могу получить от этого, где строки и специальные строки прокручиваются вместе туда, где я хочу быть, где строки прокручиваются, но специальная строка закреплена внизу и всегда видна?

Хотя в моем примере используется DataGrid, я уверен, что его можно упростить до простого прокручиваемого элемента различной высоты и элемента управления, закрепленного под ним. До сих пор я думаю, что мне нужен Canvas, а не Grid для размещения моей ScrollViewer и сопутствующей специальной строки, с некоторой логикой для регулировки высоты и положения при росте ScrollViewer (если я могу это обнаружить), но я еще не пробовал это. Есть ли лучший способ или подход Canvas лучший из доступных?

Ответы [ 2 ]

1 голос
/ 14 декабря 2013

Сначала создайте Grid для основного элемента управления и закрепленного элемента управления:

<Grid Grid.Row="0" VerticalAlignment="Top">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />               
        <RowDefinition Height="Auto" />            
    </Grid.RowDefinitions>

    <!-- The main control, that is about to stretch. -->
    <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />

    <!-- The pinned control. -->
    <TextBlock Grid.Row="1" Text="Hello World" />
</Grid>

Хитрость заключается в том, что VerticalAlignment = "Top" - когда основной элемент управления меньше доступной высоты, он переместится в верхнюю часть доступного пространства и закрепленный элемент появится под ним.

Затем поместите эту сетку в контейнер, который растягивается вертикально, например, в ряд другой сетки с высотой звезды:

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <!-- RowDefition for the Grid with the main control and the pinned control. --> 
        <!-- If you want to have some other controls, -->
        <!-- add other RowDefinitions and put these controls there.  -->
        <RowDefinition Height="*" /> 
    </Grid.RowDefinitions>

    <!-- The internal Grid for the main control and the pinned control. -->
    <Grid Grid.Row="0" VerticalAlignment="Top">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />               
            <RowDefinition Height="Auto" />            
        </Grid.RowDefinitions>

        <sdk:DataGrid Grid.Row="0" ItemsSource="{Binding YOUR_COLLECTION}" />

        <TextBlock Grid.Row="1" Text="Hello World" />
    </Grid>
</Grid>

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

1 голос
/ 18 мая 2009

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

Это, очевидно, будет работать для любого сценария, где одна строка всегда должна быть на экране, но также должна быть прикреплена к нижней части другой.

Код закрепления выглядит примерно так:

RowDefinition row = this.mainGrid.RowDefinitions[0];
if (row.Height.GridUnitType == GridUnitType.Auto)
{
    if (this.mainGrid.ActualHeight > this.ActualHeight)
    {
        row.Height = new GridLength(1, GridUnitType.Star);
    }
}
else
{
    if (this.dataGrid.DesiredSize.Height < row.ActualHeight)
    {
        row.Height = GridLength.Auto;
    }
}
...