Bluebaron
Bluebaron

Reputation: 2506

more virtualizing stack panel height/slowness issues

I need a scrollviewer around a virtualizing stackpanel populated by an items control. Clearly the height is infinity and that's why it's not virtualizing. Why?

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <ScrollViewer>
        <ItemsControl ItemsSource="{Binding InterestingHosts}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel IsItemsHost="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical">
                        <TextBlock FontSize="14"><TextBlock Text="{Binding Host.HostName}" FontWeight="Bold" FontSize="18" /> (<TextBlock Text="{Binding Host.IPAddress}" />)</TextBlock>
                        <StackPanel>
                            <StackPanel.Style>
                                <Style TargetType="StackPanel">
                                    <Setter Property="Margin" Value="10" />
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding LoggedOnUsers.Count}" Value="0">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </StackPanel.Style>
                            <TextBlock Text="The follow domain and/or enterprise admins are logged on to the host: "/>
                            <DataGrid AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="{Binding LoggedOnUsers}">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Width="200" Binding="{Binding Domain}" Header="Domain"/>
                                    <DataGridTextColumn Width="200" Binding="{Binding Name}" Header="Username"/>
                                </DataGrid.Columns>
                            </DataGrid>
                        </StackPanel>
                        <StackPanel>
                            <StackPanel.Style>
                                <Style TargetType="StackPanel">
                                    <Setter Property="Margin" Value="10" />
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Processes.Count}" Value="0">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </StackPanel.Style>
                            <TextBlock Text="The follow domain and/or enterprise admins are running processes on the host: "/>
                            <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Processes}" IsReadOnly="True">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Width="200" Header="Name" IsReadOnly="False" Binding="{Binding Name}"/>
                                    <DataGridTextColumn Width="200" Binding="{Binding Username}" Header="Username" />
                                    <DataGridTextColumn Binding="{Binding ID}" Header="ID" />
                                </DataGrid.Columns>
                            </DataGrid>
                        </StackPanel>
                        <StackPanel>
                            <StackPanel.Style>
                                <Style TargetType="StackPanel">
                                    <Setter Property="Margin" Value="10" />
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Services.Count}" Value="0">
                                            <Setter Property="Visibility" Value="Collapsed" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </StackPanel.Style>
                            <TextBlock Text="The follow domain and/or enterprise admins are authenticated for services on the host: "/>
                            <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Services}" IsReadOnly="True">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                                    <DataGridTextColumn Header="Username" Binding="{Binding Username}" />
                                    <DataGridTextColumn Header="Start Mode" Binding="{Binding StartMode}" />
                                    <DataGridTextColumn Header="State" Binding="{Binding State}" />
                                </DataGrid.Columns>
                            </DataGrid>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

Upvotes: 1

Views: 1581

Answers (2)

Rachel
Rachel

Reputation: 132548

Take a look at this answer. There's more to making an ItemsControl Virtualizing than just setting the VirtualizingStackPanel

Basically, put the ScrollViewer in your ItemsControl Template around your ItemsPresenter, and set VirtualizingStackPanel.IsVirtualizing="True" and ScrollViewer.CanContentScroll="True" on your ItemsControl

Upvotes: 3

CodeNaked
CodeNaked

Reputation: 41393

The VirtualizingStackPanel needs to be a direct child of the ScrollViewer. You can see that it implements IScrollInfo, which is what ties it to the parent ScrollViewer.

So in the case of a ListBox, there is already a ScrollViewer in the control template (which will ultimately be the parent of the VirtualizingStackPanel. The default ControlTemplate for the ItemsControl does not have a ScrollViewer, so you would need to add it there. Something like:

<Style x:Key="{x:Type ItemsControl}"
       TargetType="{x:Type ItemsControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ItemsControl}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Padding="{TemplateBinding Padding}"
                        SnapsToDevicePixels="true">
                    <ScrollViewer CanContentScroll="True">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Upvotes: 1

Related Questions