Search code examples
c#wpfscrollviewer

C# WPF - How to place a vertical scrollviewer inside a horizontal scrollviewer


Edit Turns out that the Scrollbar is there very well but due to the outer scrollbar its out of view... dump..

Any Idea how to keep the vertical Scrollbar visible even its out of sight?

This is how it actually looks when scrolling to the right: enter image description here

Prototype

I am trying to achieve something like the following:

enter image description here

Control1 is some text with about 2 lines height maximum. Control2 is a List of text-lines.

Both, control1 and control2 shall be scrolled horizontal synchroneously. Only control2 shall also have a vertival scrollbar.

Code

This is the code I tried so far:

    <Grid>
    <GroupBox Header="MyHeader" HorizontalAlignment="Stretch" Margin="5,5,5,0" VerticalAlignment="Stretch" Grid.ColumnSpan="2">
        <Grid Margin="5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <ScrollViewer Grid.Column="0" Grid.Row="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
                <DockPanel Margin="5,20,5,0">
                    <TextBlock DockPanel.Dock="Top" Text="{Binding Ruler}" Margin="6,0,0,0" FontFamily="Courier New"/>
                    <ScrollViewer DockPanel.Dock="Bottom" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="100">
                        <Border BorderThickness="0.5" BorderBrush="Black" Height="100">
                                <ItemsControl ItemsSource="{Binding PreviewRawList}" Height="100">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <TextBox Text="{Binding Path=.}" FontFamily="Courier New"/>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                        </Border>
                    </ScrollViewer>
                </DockPanel>
            </ScrollViewer>
            [...]
        </Grid>
    </GroupBox>
</Grid>

Preview

This is what it compiles. I am able to scroll vertically using the mouse-wheel but the scrollbar is just not showing up.

Preview of the code

What I tried else

I guess the problem is that due to the outer scrollviewer the inner scrollviewer gets infinite space such that it is not showing up. In other threads it were suggested to set a height for the inner scrollviewer. Well I still tried this. I set the height-property to every single element I am using in the given code. No difference concerning the scrollviewer.

I tried to interchange the DockPanel with a Grid but this only led to the ability of vertical scrolling has gone (which, as said, is working with DockPanel but only the Scrollbar is not showing up).

Thanks for any help.


Solution

  • At first I ended up with using a listview where control1 is placed within the header of the scrollview using a headerTemplate and placing the rows in the items-area using itemsTemplate for Control2.

    This almost is as perfect as expected.

    This is the code:

                <ListView Name="Ruler" Grid.Column="0" Grid.Row="0" ItemsSource="{Binding PreviewRawList}">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                            <Setter Property="BorderThickness" Value="0"/>
                            <Setter Property="Margin" Value="0"/>
                            <Setter Property="Padding" Value="0"/>
                        </Style>
                    </ListView.ItemContainerStyle>
                    <ListView.View>
                        <GridView>
                            <GridViewColumn>
                                <GridViewColumn.HeaderTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.Ruler}" Margin="2,0,0,0" FontFamily="Courier New"/>
                                    </DataTemplate>
                                </GridViewColumn.HeaderTemplate>
                                <GridViewColumn.HeaderContainerStyle>
                                    <Style TargetType="{x:Type GridViewColumnHeader}">
                                        <Setter Property="HorizontalContentAlignment" Value="Left" />
                                    </Style>
                                </GridViewColumn.HeaderContainerStyle>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <control:SelectionBindingTextBox Text="{Binding Path=.}" FontFamily="Courier New" Margin="-5,0,-5,0" BorderThickness="0" HorizontalContentAlignment="Left" BindableSelectionStart="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.RulerSelectionStart, Mode=OneWayToSource}" BindableSelectionLength="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.RulerSelectionLength, Mode=OneWayToSource}"/>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                        </GridView>
                    </ListView.View>
                </ListView>
    

    Unfortunately there is some extra-space left and right of each elements row. Due to this one can scroll a bit more to the left and also far to the right. Doing this shrinks the text inside the textbox for about 5 pixels. Thats not much but in this case it was requested to have the header and the content as well equally stretched with a fixed-width-font.

    This extra-space destroys that equal text-with between header and content.

    As in the code above I worked around that using some negative margin which isnt very nice and does not perfectly work when scrolling to the far right.