Как я могу заставить ScrollViewer работать внутри StackPanel?

В следующем WPF XAML ScrollViewer не работает (он отображает полосу прокрутки, но вы не можете прокручивать, и содержимое уходит из окна вниз).

Я могу изменить внешний StackPanel на Grid, и он будет работать.

Однако в моем приложении, из которого я воспроизвел следующий код, мне нужно иметь внешний StackPanel. Что мне нужно сделать со StackPanel, чтобы ScrollViewer отображал полезную полосу прокрутки? например, VerticalAlignment = "Stretch" Height = "Auto" не работают.

 <StackPanel>
        <ScrollViewer>
            <StackPanel>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
                <TextBlock Text="This is a test"/>
            </StackPanel>
        </ScrollViewer>
 </StackPanel>

person Edward Tanguay    schedule 29.04.2009    source источник


Ответы (7)


Вы не можете не зафиксировать высоту StackPanel. Он предназначен для неограниченного роста в одном направлении. Я бы посоветовал использовать другой Panel. Зачем вам "нужен" внешний StackPanel?

person Kent Boogaart    schedule 29.04.2009
comment
хотел сложить вещи, и используя сетку, вам нужно вручную управлять всеми строками и столбцами, но DockPanel отлично работает, поэтому я перейду на это, спасибо. - person Edward Tanguay; 29.04.2009
comment
Я согласен с Эдвардом. По моему опыту, упаковка моих DataGrids в DockPanel и установка DockPanel.Dock = Top для каждой DataGrid отлично работала. - person BitsAndBytes; 07.09.2015
comment
Какой альтернативный элемент управления мне следует использовать в UWP? Нет DockPanel. Спасибо. - person Jan Chalupa; 05.03.2016
comment
Для UWP вы можете использовать RelativePanel - person xmashallax; 04.04.2016
comment
Проклятье stackpanel, мне всегда приходится заменять ее сеткой на UWP, они должны изменить ее поведение, это единственная панель, которая работает таким образом - person Alberto Rivelli; 23.04.2016
comment
исправление высоты внутренней панели стека сделает это, потому что тогда средство просмотра прокрутки возьмет высоту из своего дочернего элемента, но в случае, если высота панели внутреннего стека будет расти, как и средство просмотра прокрутки. Короче говоря, до тех пор, пока высота ScrollViewer не станет NaN, он будет принимать размер в соответствии с его содержимым. С другой стороны, если установлена ​​высота ScrollViewer, он не будет расширяться без его содержимого. Так что, скорее всего, это лучший вариант. - person Kylo Ren; 06.06.2016

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

Кроме того, вам необходимо убедиться, что вы установили для свойства CanContentScroll средства просмотра прокрутки значение True, вот пример:

  <ScrollViewer Grid.Row="1" Margin="299,12,34,54" Name="ScrollViewer1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Height="195" CanContentScroll="True">
        <StackPanel Name="StackPanel1" OverridesDefaultStyle="False"  Height="193" Width="376" VerticalAlignment="Top" HorizontalAlignment="Left"></StackPanel>
  </ScrollViewer>
person Rob    schedule 08.07.2010
comment
Где находится свойство CanContentScroll? См. msdn.microsoft. ru / en-us / library / - person gideon; 24.11.2010
comment
Giddy ›Перейдите по этой ссылке: - msdn.microsoft.com/en-us/ библиотека / ms612683.aspx - person Kushal Waikar; 26.11.2010
comment
Вам необходимо убедиться, что вы установили для свойства CanContentScroll средства просмотра прокрутки значение True - я до сих пор не могу поверить, что это не значение по умолчанию для элемента управления с именем ScrollViewer. - person Andrea Antonangeli; 29.08.2017
comment
@AndreaAntonangeli Я не думаю, что 'CanContentScroll 'означает то, что вы думаете. Когда «истинная» прокрутка выполняется для каждого элемента (или части контента), когда «ложная» прокрутка все еще происходит, но на уровне пикселей - person mcalex; 06.03.2019

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

<ScrollViewer>
  <ItemsControl ItemsSource="{Binding Pages}"/>
</ScrollViewer>

который работал нормально. «Страницы», на которые ссылается привязка, были действительно разными, сложными UserControls, и я хотел, чтобы на некоторых из них были только полосы прокрутки. Итак, я удалил средство просмотра прокрутки:

 <ItemsControl ItemsSource="{Binding Pages}"/>

Затем я поставил ScrollViewer как верхний элемент среди тех элементов управления, где я хотел. Однако это не сработало. Контент просто утекал со страницы. Сначала я не думал, что этот вопрос / ответ может мне помочь, но я понял, что ItemPanel по умолчанию для ItemsControl - это StackPanel. Итак, я решил свою проблему, указав ItemsPanel, который не был StackPanel:

<ItemsControl ItemsSource="{Binding Pages}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
person T.J.Kjaer    schedule 16.09.2011

Вот как это работает:

<Window x:Class="TabControl.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:local="clr-namespace:TabControl"
    Title="MainWindow"    Height="300"   
    DataContext="{Binding RelativeSource={RelativeSource Self}}"         
    >    
<StackPanel>
    <ScrollViewer Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}" >
        <StackPanel >
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
            <TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
        </StackPanel>
    </ScrollViewer>
</StackPanel>

By binding the ScrollViewer's Height to Window's Inner Height.

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

Вывод:

«Полоса

person Kylo Ren    schedule 09.02.2016
comment
Это вроде как близко, но не совсем. Некоторый элемент управления, который является предком для ScrollViewer, но находится между Border и ScrollViewer, может иметь поле (у меня есть), и привязка к значению ActualHeight этого не улавливает. - person Alan McBee; 04.06.2016
comment
@AlanMcBee: да, может быть много возможных случаев, когда он не будет работать идеально, но это самый простой случай для иерархии элементов управления, которую я дал решение. Но, учитывая логику, все, что вам нужно сделать, в большинстве случаев измените тип предка в вашей привязке, и он снова должен работать идеально. Суть исправления заключалась в том, что в иерархии существовал элемент пользовательского интерфейса, который мог бы помочь нам зависеть от высоты (не обязательно границы), логика может оставаться такой же, пока вы можете найти надежную высоту. Надеюсь, это имеет смысл, иначе опубликуйте свою проблему как вопрос, я постараюсь помочь. :) - person Kylo Ren; 04.06.2016
comment
x:Type не найдено. - person Bigeyes; 16.12.2016
comment
@Bigeyes, какую версию .net и версию VS вы используете? - person Kylo Ren; 19.12.2016
comment
@KyloRen. Visual Studio 2010 и .Net 4.0. - person Bigeyes; 19.12.2016
comment
@Bigeyes x: Type - это собственный синтаксис WPF, должна быть проблема с вашим дизайнером или компилятором .. - person Kylo Ren; 22.12.2016
comment
@KyloRen. Ты прав. Я попытался использовать его в проекте Silverlight с дочерним окном telerik. Но пока я понятия не имею. :-) - person Bigeyes; 22.12.2016

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

        <Grid Style="{StaticResource LayoutRootStyle}">
    <Grid.RowDefinitions>
        <RowDefinition Height="160"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>        

    <!-- Vertical scrolling grid used in most view states -->    

        <ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal">
                <GridView>
                ...
                </GridView>
            </StackPanel>
        </ScrollViewer>        
person Luis Delgado    schedule 13.01.2013

Вот как бы я сделал это, если бы ваша панель стека была внутри сетки:

<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
    <StackPanel MaxHeight="{Binding Path=Height,RelativeSource={RelativeSource 
              AncestorType=Grid}}">
    </StackPanel>
</ScrollViewer>
person Dominic Picard    schedule 22.01.2019

Перемещение Grid.Row = "1" из StackPanel в ScrollViewer полностью решило эту проблему для меня.

У меня был длинный список из 40 элементов для отображения в StackPanel, но отображались только первые 20.

    <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <StackPanel x:Name="ContentPanel" Margin="12,0,12,0">
        <TextBlock Text="{Binding Line1}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        <TextBlock Text="" Margin="10,-2,10,0" Style="{StaticResource PhoneTextNormalStyle}" />
        ...
        </StackPanel>
    </ScrollViewer>
person user3522840    schedule 11.04.2014