XAML: Limiting size of control nested in ScrollVie

2019-08-30 07:48发布

问题:

I am trying to nest a user control within a ScrollViewer making its height the same as height of the ScrollViewer, which may vary based on screen size (i.e. not fixed).

The ScrollViewer is responsible for horizontal scrolling and has vertical scrolling disabled. The nested user control has a grid with two rows - "header" (another user control) and a ListView. This ListView should be vertically scrollable. The objective here is that the "header" stays in place and large content of the ListView is scrollable vertically. Otherwise, if the containing ScrollViewer is responsible for vertical scrolling, the "header" will go out of visible area on vertical scrolling of the ScrollViewer.

My question is: how can I make nested user control's height the same as the height of the ScrollViewer (which is not fixed)? If nested user control's height is not specified/constrained (equal to 540 in the snippet below), the ListView takes all the space it needs and thus it is not scrollable vertically. In other words, I think I need to remove hard-coded height "540" from the and somehow make its height the same as its parent (ScrollViewer). There might be a better solution, but constraining height of the user control seems to be one way to achieve the objective.

Here is the relevant XAML of the page with ScrollViewer:

<Grid x:Name="MainGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="140"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid Grid.Row ="1">
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden">
            <userCtrl:MyUserControl Height="540"/>
        </ScrollViewer>

    </Grid>

Here is XAML snippet of the user control

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="120"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <local:HeaderRow x:Name="headerRow"></local:HeaderRow>
    <ListView x:Name="gridBodyListView" Grid.Row="1 "/>
</Grid>

回答1:

I don't quite understand the scenario. I tried your XAML and it produced a ListView inside a ScrollViewer with horizontal content scrollable and vertical content clipped. If this is not what you want, can you explain what exactly is trying to be achieved with some more context?

https://github.com/finnigantime/Samples/tree/master/examples/Win8Xaml/ListView_LimitSizeInSV

Note that ListView already has .Header and .HeaderTemplate properties, and already has a ScrollViewer surrounding its ItemsPanel in its template. You can set the attached ScrollViewer properties on the ListView directly to switch between horizontal/vertical scrolling (Horizontal/VerticalScrollBarVisibility and Horizontal/VerticalScrollMode).



回答2:

As noted by @serg_o in comments, the solution to this is to bind the height of the child of the ScrollViewer to the ActualHeight of the ScrollViewer by naming the ScrollViewer and then using a binding by ElementName.

<Grid Grid.Row ="1"> 
    <ScrollViewer x:Name="scrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden"> 
        <userCtrl:MyUserControl Height="{Binding ElementName=scrollViewer, Path=ActualHeight}"/> 
    </ScrollViewer> 
</Grid>