Sierra

Scroll behaviour when you have an ItemsControl within an ItemsControl

04 Jul 2024, 15:37

Greetings,

I have a bit of a curious issue which I can't seem to resolve myself. I have an ItemsControl which loads a collection of items. Let's call it Parent. The items are organized in a StackPanel with Vertical Orientation and each item consists of a TextBlock (title) and another ItemsControl which loads another collection of items. These items are interactive and are organized with a WrapPanel. Essentially, I'm using the Parent to render a list of groups and each group renders its own collection of items.

My expectation is that I'd be able to scroll vertically, but I'm encountering some issues. The Parent's vertical scrollbar triggers, but it works only if I click and drag the actual scrollbar. It doesn't respond to the mouse wheel which I presume is because the MousePreview is stolen by the child ItemsControl. I'm also unable to scroll items by moving focus with keyboard/gamepad. If the focus moves to an item that is outside of the bounds the content doesn't scroll.

Is there a workaround for this? I've attached a wireframe of my setup.

Note: I'm not using fixed height as I'd like my layout to adapt to the window size.
Attachments
Screenshot 2024-07-04 163004.png
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: Scroll behaviour when you have an ItemsControl within an ItemsControl

04 Jul 2024, 17:47

Hi,
My expectation is that I'd be able to scroll vertically, but I'm encountering some issues.
Is quite possible that the problem is that your inner ItemsControl is defining a ScrollViewer in its template that is handling the mouse wheel events. As that inner ItemsControl always shows all the items, you can just change its template to just include an ItemsPresenter.

I tried the following xaml and it scrolls perfectly fine even with nested ItemsControls:
<Border BorderBrush="Black" BorderThickness="2" Width="600" Height="300">
    <ItemsControl ItemsSource="{Binding Groups}">
      <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
          <ScrollViewer Focusable="False">
            <ItemsPresenter/>
          </ScrollViewer>
        </ControlTemplate>
      </ItemsControl.Template>
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <StackPanel>
            <TextBlock Text="{Binding Name}"/>
            <ItemsControl ItemsSource="{Binding Items}">
              <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                  <WrapPanel/>
                </ItemsPanelTemplate>
              </ItemsControl.ItemsPanel>
              <ItemsControl.ItemTemplate>
                <DataTemplate>
                  <Rectangle Width="50" Height="50" Fill="Red" Margin="10"/>
                </DataTemplate>
              </ItemsControl.ItemTemplate>
            </ItemsControl>
          </StackPanel>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
</Border>
I'm also unable to scroll items by moving focus with keyboard/gamepad. If the focus moves to an item that is outside of the bounds the content doesn't scroll.
By default focused elements try to make themselves visible when inside a ScrollViewer, perhaps it has something to do with virtualization. Just to confirm, could you please override the outer ItemsControl.ItemsPanel with a simple StackPanel and see the behavior then?
 
Sierra

Re: Scroll behaviour when you have an ItemsControl within an ItemsControl

04 Jul 2024, 17:57

Heya,

Thanks for the reply. In order for this to work shouldn't the <ScrollViewer Focusable="False"> be set within the child ItemsControl Template and not on the parent groups one?Ю

EDIT: Yep, removing the ScrollViewer on the child ItemsControl is what solved it for me. Here's the XAML that worked for me.
<ItemsControl
	ItemsSource="{Binding ItemGroups}"
	HorizontalAlignment="Stretch"
	VerticalAlignment="Stretch">	
	
	<ItemsControl.Template>
		<ControlTemplate TargetType="ItemsControl">
			<ScrollViewer VerticalScrollBarVisibility="Auto">
				<ItemsPresenter/>
			</ScrollViewer>
		</ControlTemplate>
	</ItemsControl.Template>

	<ItemsControl.ItemTemplate>
		<DataTemplate>
			<StackPanel>
				<TextBlock
   					Text="{Binding Name}"
                                        FontSize="18"/>

				<ListBox
					ItemsSource="{Binding Items}"
					ItemContainerStyle="{DynamicResource Style.Item}"
					ItemTemplate="{DynamicResource DataTemplate.Item}"
					Padding="0">

                                        <ListBox.Template>
						<ControlTemplate TargetType="ListBox">
							<!-- This is where I just left the template without a ScrollViewer -->
							<ItemsPresenter/>
						</ControlTemplate>
                                        </ListBox.Template>

                                        <ListBox.ItemsPanel>
						<ItemsPanelTemplate>
                                                    <WrapPanel ItemWidth="76" ItemHeight="76"/>
						</ItemsPanelTemplate>
                                        </ListBox.ItemsPanel>
				</ListBox>
			</StackPanel>
		</DataTemplate>
	</ItemsControl.ItemTemplate>
</ItemsControl>
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: Scroll behaviour when you have an ItemsControl within an ItemsControl

04 Jul 2024, 18:26

That was the idea, great to hear it worked!

Who is online

Users browsing this forum: Bing [Bot] and 4 guests