简体   繁体   中英

Scrollviewer within another

I've started using WPF not long ago and I've been dealing with a ScrollViewer problem that seems actually pretty common : I have a ScrollViewer with content of varying, which is displayed together with other content, and the entire thing is inside another ScrollViewer. The whole thing looks something like that :

<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
    <StackPanel Orientation="Vertical">
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
            <StackPanel Orientation="Vertical">
                <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
            </StackPanel>
        </ScrollViewer>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
    </StackPanel>
</ScrollViewer>

What I want is for the inner ScrollViewer to start reducing its content before the outer one, meaning if I have all this in a window and reduce the window size, I want the ScrollViewer with blue rectangle to start reducing its content and displaying its scrollbar before the outer one, the one containing orange rectangle does.

After looking on the internet for a long while, I found two main advices : first one is to avoid using StackPanel - in this simplified example I could obviously use a Grid, in practice on the real project I'm not sure I could since the content I put in this ScrollViewer is of varying size depending what I'm binding in there. Second one is something I found on an answer to an eerily similar question :

Nested Scroll Areas

Which seemed to work well at first. The resulting xaml becomes :

<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
    <StackPanel Orientation="Vertical">
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <local:RestrictDesiredSize MinHeight="60">
            <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
                <StackPanel Orientation="Vertical">
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                </StackPanel>
            </ScrollViewer>
        </local:RestrictDesiredSize>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
    </StackPanel>
</ScrollViewer>

But now I have the opposite problem : the inner scrollviewer is always stuck at a height of 60, even if I expand the window, but I would like it to take as much space as possible - display all the blue rectangles and hide the scrollbar if possible

Does anyone know how to accomplish that ?

EDIT :

I've found a temporary solution that's not perfect by using a DockPanel somewhere instead of a StackPanel, I'm guessing it would really be easier to solve this by avoiding stackpanels all together ? Here's the last version I have

<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
    <DockPanel>
        <StackPanel DockPanel.Dock="Top">
            <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
            <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        </StackPanel>
        <StackPanel DockPanel.Dock="Bottom">
            <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
            <Rectangle Height="50" Width="50" Margin="5" Fill="Orange"/>
        </StackPanel>
        <local:RestrictDesiredSize MinHeight="60">
            <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
                <StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                    <Rectangle Height="50" Width="50" Margin="5" Fill="Blue"/>
                </StackPanel>
            </ScrollViewer>
        </local:RestrictDesiredSize>
    </DockPanel>
</ScrollViewer>

Now it's not perfect because part of the content is docked to the bottom but I'm going to try this as a work-around for now unless I find something better.

I have solved this problem in the past by binding the appropriate width to the parent ActualWidth using RelativeSource .

See How do I use WPF bindings with RelativeSource? .

Snoop is also very useful for working out how to find the property you want in the Visual Tree, see my tutorial on Snoop at ReSharper WPF error: "Cannot resolve symbol "MyVariable" due to unknown DataContext" .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM