开发者

ScrollViewer in ItemsControl - ScrollBar not shown but working

开发者 https://www.devze.com 2023-04-12 23:07 出处:网络
This is not your average \"My ScrollViewer isn\'t working\" question... Assume a window with a grid. The sizes of column 0 and row 1 are set to Auto, column 1 and row 0 are set to *. (important)

This is not your average "My ScrollViewer isn't working" question...

Assume a window with a grid. The sizes of column 0 and row 1 are set to Auto, column 1 and row 0 are set to *. (important)

In cell [0, 0] there is an ItemsControl with a Template with a StackPanel inside a ScrollViewer inside a Grid. The reason is simple: Show a scroll bar if not all items in the ItemsControl can be displayed. The visibility of the vertical scrollbar is set to Auto (important).

In Cell [1, 1] there is a Button that displays its width.

If the window is too small too display all items in the ItemsControl this will lead to the following: The scroll bar will be there but it is not visible. It is working, because I can scroll using the mouse wheel. The reason seems to be that the grid column in which the ItemsControl is contained is not automatically extended to make space for the scrollbar.

If I change (nearly) any of the parameters, the scroll bar is displayed as expected and the second column is reduced in size. Can anyone explain this odd behavior?


Additional Info:

The following parameter changes will lead to the scrollbar becoming visible:

  1. Changing size of column 0 to *
  2. Changing size of column 1 to Auto
  3. Changing size of row 1 to *
  4. Removing the Button.
  5. Moving the Button to [0, 1] or [1, 0]
  6. Manually setting the width of the ItemsControl.
  7. Setting the VerticalScrollBarVisibility of the ScrollViewer in the ItemsControl to Visible.

However, changing the button in [1, 1] to something else, e.g. another ItemsControl doesn't change the strange behavior, so it has nothing to with the button. Furthermore, changing the width of the Button to something that is smaller than the second column, also doesn't remove that behavior.


Complete sample code for reproduction:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="343" Width="253">
  <Grid>
    <Grid.ColumnDefinitions>
      <C开发者_StackOverflow中文版olumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <ItemsControl>
      <ItemsControl.Template>
        <ControlTemplate>
          <Grid>
            <Grid.RowDefinitions>
              <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <ScrollViewer VerticalScrollBarVisibility="Auto">
              <StackPanel IsItemsHost="True" />
            </ScrollViewer>
          </Grid>
        </ControlTemplate>
      </ItemsControl.Template>
      <ItemsControl.Items>
        <Button Content="Column1" Height="500" />
      </ItemsControl.Items>
    </ItemsControl>
    <Button Content="{Binding ActualWidth, RelativeSource={RelativeSource Self}}"
            Grid.Column="1" Grid.Row="1" />
  </Grid>
</Window>


Looks like it might be a known bug in WPF. This question deals with a ListBox's ScrollViewer, but I think the principal is the same.

As an alternative, you could add something behind the ScrollViewer that has it's width bound to the ScrollViewer's ActualWidth, which will force the column to draw the correct size

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <ScrollViewer x:Name="Test" Grid.Row="0" Grid.Column="0" 
                  VerticalScrollBarVisibility="Auto">
        <Button Content="Column1" Height="500" />
    </ScrollViewer>

    <Grid Grid.Column="0" Grid.Row="0" 
          Width="{Binding ElementName=Test, Path=ActualWidth}" />

    <Button Content="{Binding ActualWidth, RelativeSource={RelativeSource Self}}"
        Grid.Column="1" Grid.Row="1" />
</Grid>
0

精彩评论

暂无评论...
验证码 换一张
取 消