WPF Layout - получение столбца для заполнения доступного пространства - PullRequest
2 голосов
/ 04 декабря 2009

У меня есть ListBox, у которого в шаблоне есть сетка для 4 столбцов. Один столбец - это фактический текст ListBox. Я хочу, чтобы этот столбец заполнял доступное горизонтальное пространство.

Определения столбцов:

<ControlTemplate TargetType="ListBoxItem">
    <Grid ScrollViewer.CanContentScroll="True" Margin="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20" />
            <ColumnDefinition Width="50" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="30" />
        </Grid.ColumnDefinitions>
        <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding IsSelected,
                  RelativeSource={RelativeSource TemplatedParent},
                  Mode=TwoWay}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="{Binding Id}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="{Binding Title}" />
        <Button HorizontalAlignment="Right" Grid.Column="3" Tag="{Binding Id}" Margin="5,0,5,0">-&gt;</Button>
    </Grid>
</ControlTemplate>

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

ListBox обернут в ScrollViewer, чтобы позволить вертикальную прокрутку (я предполагаю, что это то, что меня портит)

Есть идеи о том, как заставить третий столбец заполнить только доступное пространство и не более?

Ответы [ 4 ]

1 голос
/ 04 декабря 2009

Требуется ли вам режим управления ListBox или вы используете его только для макета.

Если вы используете его только для разметки, вы можете поменять ListBox на ItemsControl внутри ScrollViewer.

Этот код (вырезанный для работы в дизайнере) показывает это:

<ScrollViewer>
    <ItemsControl>
        <!--<ListBox>-->
        <Grid Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>

            <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="True" />
            <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="Id" />
            <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="Title" />
            <Button HorizontalAlignment="Right" Grid.Column="3" Margin="5,0,5,0">-&gt;</Button>
        </Grid>
        <!--</ListBox>-->
    </ItemsControl>
</ScrollViewer>

У ListBox есть свойство убивать ширину своих детей, как у TreeView. Так что, если вы можете избежать его использования по причинам, связанным с макетом, это могут быть ваши самые быстрые варианты.

В противном случае вам нужно будет привязать ширину вас Grid к ширине фиктивного объекта за пределами ListView, но грязная сторона имеет дело с изменением ширины, когда полоса прокрутки появляется / исчезает.

1 голос
/ 04 декабря 2009

Зачем вам нужно обернуть ListBox в ScrollViewer? ListBox автоматически отображает ScrollViewer, когда его содержимое не помещается в доступное пространство. Вы можете удалить его из XAML, и он все равно должен работать. По крайней мере, это для меня. :)

Я опробовал ваш ControlTemplate, и он, кажется, работал очень хорошо. Проблема заключается в том, что в то время как 3-й столбец изменяется до ширины ListBox, если текст в 3-м столбце очень длинный, 4-й столбец не будет отображаться, пока весь текст не станет видимым.

Я также попробовал другой метод компоновки, который не уверен насчет производительности, но идея заключалась в том, чтобы использовать DockPanel вместо Grid. Я добавил третий столбец последним в XAML, чтобы он заполнил оставшееся пространство, и закрепил его слева (я закрепил 4-й столбец справа). Было бы желательно отобразить всю строку в 3-м столбце. Я не знаю, почему это происходит, и почему текст не будет переноситься или использовать многоточие, когда свободного места недостаточно для отображения текста.

<Window.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <DockPanel Width="Auto">
                        <CheckBox Width="20" VerticalAlignment="Center" DockPanel.Dock="Left" IsChecked="{Binding IsSelected,
                                        RelativeSource={RelativeSource TemplatedParent},
                                        Mode=TwoWay}" />
                        <TextBlock Width="50" VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="hi" />
                        <Button Width="30" HorizontalAlignment="Right" DockPanel.Dock="Right" Margin="5,0,5,0">-&gt;</Button>
                        <TextBlock VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="afdjfksdhahjklfadshjlasffasdlhjsafdlhjasdfasfhdjlaslfhdjsfdhjlsfdlhjsfdhjsfdddsd" TextTrimming="CharacterEllipsis" TextWrapping="WrapWithOverflow" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>   
0 голосов
/ 08 декабря 2009

Я наконец понял это.

Содержащий список, необходимый для отключения горизонтальной полосы прокрутки следующим образом:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" 

Как только я это сделал, размер сетки идеально подходил.

На днях я выясню, как работает весь этот "декларативный материал".

0 голосов
/ 04 декабря 2009

Да, я хотел бы предположить, что средство просмотра прокрутки вас портит, вы можете привязать ширину сетки к фактической ширине родительских объектов, так что есть определенный размер, который * должен фактически заполнить.

...