1
\$\begingroup\$

I need to handle a resizable WPF ScrollViewer that scrolls vertically and stretches horizontally and contains stretched wrappable TextBoxes.

I have the following XAML WPF layout (the smallest example I have managed to produce):

<Window x:Class="ESiftClient.TestWindow1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TestWindow1" Height="800" Width="1000">
    <!--Main grid-->
    <Grid>
        <Grid.RowDefinitions>
            <!--Top fixed size Tools controls-->
            <RowDefinition Height="115"></RowDefinition>
            <!-- Excel like scrollable grid  -->
            <RowDefinition Height="200" MinHeight="150"></RowDefinition>
            <!-- Grid splitter -->
            <RowDefinition Height="Auto"></RowDefinition>
            <!-- Text boxes with wrappable text editor, there I have the problem-->
            <RowDefinition Height="*" MinHeight="150"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Border Grid.Row="0" Background="Gray">
            <Label Content="Some controls within a grid here"></Label>
        </Border>

        <DockPanel Grid.Row="1" Grid.Column="0" LastChildFill="True" Width="Auto" 
                   Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,0,0,0" >
            <Grid Width="Auto" Height="Auto" VerticalAlignment="Stretch" HorizontalAlignment="Left">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="*"></RowDefinition>
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left" >
                    <Label Content="Title and buttons" />
                </StackPanel>
                <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
                    <Grid>
                        <!-- This grid is excel like grid with many rows and columns-->
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>
                        <Label Content="ItemsControl Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="0" Grid.ColumnSpan="2" />
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="1" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="2" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="3" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="4" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="5" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="6" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="7" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="8" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="9" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="9" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="9" Grid.ColumnSpan="2"/>
                        <Label Content="Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label Label " Grid.Row="9" Grid.ColumnSpan="2"/>
                    </Grid>
                </ScrollViewer>
            </Grid>
        </DockPanel>

        <GridSplitter Grid.Row="2" Grid.Column="0" ResizeDirection="Rows" Height="5" 
                      HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"
                      KeyboardNavigation.IsTabStop="False" 
                      />

        <Grid Grid.Row="3">
            <Grid.RowDefinitions>
                <RowDefinition Height="50"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <DockPanel Grid.Row="0" 
                   LastChildFill="True" Width="Auto" 
                   Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
                    <Label Content="Title and buttons" />
                </StackPanel>
            </DockPanel>
            <!--HorizontalScrollBarVisibility="Hidden" must be set, otherwise it shows horizontal scrollbar -->
            <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" 
                   x:Name="ScrollViewerXML" Grid.Row="1">
                <!--!!! Hacking the Width of the Grid using Binding !!! -->
                <Grid Height="500" VerticalAlignment="Top"  Grid.Row="1" x:Name="GridWithTextBoxes"
                      Width="{Binding ActualWidth, ElementName=ScrollViewerXML}"
                      >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="100"></ColumnDefinition>
                        <!--This column needs to have the size not overflowing parent control size-->
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Border Background="Gray">
                        <StackPanel Orientation="Vertical" Margin="0,5,5,0" Grid.Row="0" Grid.Column="0">
                            <Label Content="Title"  FontWeight="Bold" HorizontalAlignment="Right"></Label>
                        </StackPanel>
                    </Border>
                    <Border Grid.Row="0" Grid.Column="1" Background="Gray">
                         <!-- Here comes the problem, without the Binding Hack the text box has auto size Width of 16578 and I need the Width to not to overflow actual Grid Column Width-->
                        <TextBox TextWrapping="Wrap"                                                                              
                                     Width="Auto"
                                     MinHeight="60" 
                                     AcceptsReturn="True" 
                                     FontSize="14" 
                                     Margin="0,5,5,5">
                            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ultricies, libero eu pellentesque laoreet, ligula arcu lobortis orci, non molestie turpis nunc vel mi. Nulla dapibus neque eget nulla sodales semper. Donec luctus, quam ut tincidunt condimentum, magna purus luctus risus, at malesuada ligula est in libero. Fusce sit amet lorem in dui pharetra vestibulum a euismod sem. Suspendisse tincidunt elementum sapien vel sollicitudin. Phasellus nec arcu ipsum. Curabitur lacinia hendrerit nisl non accumsan. Nam id nunc odio. Quisque dapibus sed urna mattis tristique. Quisque ornare condimentum erat ut aliquet. Aenean interdum interdum erat, ut sagittis metus commodo ac. Maecenas eu augue eget lectus aliquam finibus quis vel nulla. Fusce dui purus, efficitur quis dapibus eget, pulvinar a massa. Praesent pellentesque nunc sit amet nibh dictum gravida.
Suspendisse dignissim turpis nec enim scelerisque aliquet. Proin rhoncus viverra efficitur. Etiam sed faucibus diam, at sagittis ante. Maecenas augue est, sodales vitae sem ac, auctor pellentesque orci. Donec placerat ligula vel nibh pellentesque consequat. Nunc non ipsum lorem. Mauris quis commodo purus, at ultricies nulla. Aenean ut finibus mi. Proin condimentum aliquam ornare.
Vestibulum id pretium felis. Fusce at rutrum erat. Vivamus nisi quam, tincidunt a lectus nec, volutpat rutrum libero. Duis ac turpis ac dolor iaculis rhoncus. Morbi finibus sem id mi commodo, in ultricies ante sollicitudin. Phasellus eu tellus non erat pulvinar commodo id ut nisi. Nulla tristique efficitur ipsum ac feugiat.
Nunc laoreet massa id nisi sagittis tempus. Phasellus viverra nibh tellus, nec dignissim elit vehicula eget. Etiam lobortis est et nulla volutpat, in varius turpis malesuada. Nullam a tempus ante. Praesent libero dui, laoreet vitae eleifend non, aliquet vitae dolor. Nunc ac est non lacus imperdiet semper. Ut consectetur dolor neque, ut maximus est ultricies quis. Aliquam porta mi eu sodales semper. Nulla tristique feugiat mauris facilisis eleifend. Suspendisse vel magna dignissim, interdum massa nec, posuere urna. Curabitur vehicula commodo ligula, quis imperdiet risus accumsan at. Vestibulum erat enim, gravida a rhoncus quis, tristique et erat.
Vivamus pulvinar pharetra scelerisque. Nunc arcu ex, imperdiet at mi a, egestas interdum diam. Mauris ornare ut massa nec dignissim. Donec suscipit quis nisi quis lacinia. Donec risus massa, pretium at orci id, consequat vulputate orci. Nam bibendum orci id libero placerat, sed venenatis turpis vestibulum. Vestibulum ut elit quis lorem feugiat suscipit eu nec neque. Sed in mauris vel sapien sagittis commodo a auctor dolor. Nam eu ultricies turpis. Mauris pellentesque molestie hendrerit.
                        </TextBox>
                    </Border>
                    <Border Grid.Row="1" Grid.Column="0" Background="Gray">
                        <StackPanel Orientation="Vertical" Margin="0,0,5,0" >
                            <Label Content="Title" FontWeight="Bold"  HorizontalAlignment="Right"></Label>
                        </StackPanel>
                    </Border>
                    <Border Grid.Row="1" Grid.Column="1" Background="Gray" 
                                HorizontalAlignment="Left">
                        <TextBox TextWrapping="Wrap"                                      
                                     Width="Auto"
                                     MinHeight="70" 
                                     AcceptsReturn="True" 
                                     FontSize="14" 
                                     Margin="0,0,5,5">
                            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ultricies, libero eu pellentesque laoreet, ligula arcu lobortis orci, non molestie turpis nunc vel mi. Nulla dapibus neque eget nulla sodales semper. Donec luctus, quam ut tincidunt condimentum, magna purus luctus risus, at malesuada ligula est in libero. Fusce sit amet lorem in dui pharetra vestibulum a euismod sem. Suspendisse tincidunt elementum sapien vel sollicitudin. Phasellus nec arcu ipsum. Curabitur lacinia hendrerit nisl non accumsan. Nam id nunc odio. Quisque dapibus sed urna mattis tristique. Quisque ornare condimentum erat ut aliquet. Aenean interdum interdum erat, ut sagittis metus commodo ac. Maecenas eu augue eget lectus aliquam finibus quis vel nulla. Fusce dui purus, efficitur quis dapibus eget, pulvinar a massa. Praesent pellentesque nunc sit amet nibh dictum gravida.
Suspendisse dignissim turpis nec enim scelerisque aliquet. Proin rhoncus viverra efficitur. Etiam sed faucibus diam, at sagittis ante. Maecenas augue est, sodales vitae sem ac, auctor pellentesque orci. Donec placerat ligula vel nibh pellentesque consequat. Nunc non ipsum lorem. Mauris quis commodo purus, at ultricies nulla. Aenean ut finibus mi. Proin condimentum aliquam ornare.
Vestibulum id pretium felis. Fusce at rutrum erat. Vivamus nisi quam, tincidunt a lectus nec, volutpat rutrum libero. Duis ac turpis ac dolor iaculis rhoncus. Morbi finibus sem id mi commodo, in ultricies ante sollicitudin. Phasellus eu tellus non erat pulvinar commodo id ut nisi. Nulla tristique efficitur ipsum ac feugiat.
Nunc laoreet massa id nisi sagittis tempus. Phasellus viverra nibh tellus, nec dignissim elit vehicula eget. Etiam lobortis est et nulla volutpat, in varius turpis malesuada. Nullam a tempus ante. Praesent libero dui, laoreet vitae eleifend non, aliquet vitae dolor. Nunc ac est non lacus imperdiet semper. Ut consectetur dolor neque, ut maximus est ultricies quis. Aliquam porta mi eu sodales semper. Nulla tristique feugiat mauris facilisis eleifend. Suspendisse vel magna dignissim, interdum massa nec, posuere urna. Curabitur vehicula commodo ligula, quis imperdiet risus accumsan at. Vestibulum erat enim, gravida a rhoncus quis, tristique et erat.
Vivamus pulvinar pharetra scelerisque. Nunc arcu ex, imperdiet at mi a, egestas interdum diam. Mauris ornare ut massa nec dignissim. Donec suscipit quis nisi quis lacinia. Donec risus massa, pretium at orci id, consequat vulputate orci. Nam bibendum orci id libero placerat, sed venenatis turpis vestibulum. Vestibulum ut elit quis lorem feugiat suscipit eu nec neque. Sed in mauris vel sapien sagittis commodo a auctor dolor. Nam eu ultricies turpis. Mauris pellentesque molestie hendrerit.
                        </TextBox>
                    </Border>
                </Grid>
            </ScrollViewer>
        </Grid>
    </Grid>
</Window>

The problem is that I need to modify the Width of the bottom Grid named GridWithTextBoxes with Binding to the parent element (ScrollViewer) and I believe this is a hack and there must be a better way to do it.

When I remove the Binding Width hack, the TextBoxes with wrappable long text do not wrap but extend to the maximum Width without wrapping.

Could the same behavior be achieved in some other way without setting HorizontalScrollBarVisibility="Hidden" on the ScrollViewer named ScrollViewerXML and without binding the Width of the Grid named GridWithTextBoxes to the ActualWidth of the ScrollViewer named ScrollViewerXML?

\$\endgroup\$
2
\$\begingroup\$

I believe this is the correct way to accomplish your goal.

The ScrollViewer is designed so as not to restrict the size of its content to its viewable area, but in this case (at least for the width) this is exactly what you want. So in order to achieve vertical scrolling without horizontal scrolling, you must match the contents' width to that of the ScrollViewer.

To do this you have two options:

  1. Explicitly set the width of each control. This is not recommended since WPF is designed to be dynamic and reactive to changes in layout.
  2. Bind the width of the content to the width of the ScrollViewer. This is perfect since you want the content width to match the container width. The binding will ensure that.

You elected the better option. Well done.

P.S. I've done this in my code many times. It does feel hackish at first, but it's the right way to do it.

P.P.S. There may be a gotcha in here that your ScrollViewer may come with some padding (space on the inside before it shows content) or a border. Both of these can cause your Grid to be a few pixels too wide.

\$\endgroup\$
  • \$\begingroup\$ Ok, but in reality I also had to write value converter to make the Grid width few points smaller than that of the parent ScrollViewer element, as you write in P.P.S. So you think it is a pretty normal way of handling ScrollViewer that should only scroll in one direction and should contain stretched elements like wrappable TextBoxes? \$\endgroup\$ – Vojtěch Dohnal Nov 17 '15 at 18:18
  • \$\begingroup\$ Yes I do. It's how I would handle this scenario. \$\endgroup\$ – gregsdennis Nov 17 '15 at 19:15
  • \$\begingroup\$ @VojtěchDohnal one more thing. In your converter, you may want to subtract the border thickness and padding values rather than specific pixel amounts. This will help if/when you decide to restyle the ScrollViewer. \$\endgroup\$ – gregsdennis Nov 20 '15 at 1:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.