问题
I want to add a header to my ListBoxes and I do this by using a template. The problem is that if I extend the ListBox's template it seems that the listbox's virtualizingstackpanel doesn't work anymore as expected: it loads all content before I can scroll it.
I found some relevant questions in stackoverflow like this (VirtualizingStackPanel stops working when overriding the default control template for ScrollViewer) but the solution given there cannot be applied to WP7: I can't find the property named "CanContentScroll" of the scrollviewer.
my code
<Style x:Key="ListBoxStyle1" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer x:Name="ScrollViewer"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Padding="{TemplateBinding Padding}">
<StackPanel>
<TextBlock Text="..."/>
<ItemsPresenter/>
</StackPanel>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
回答1:
To be honest, I'm really not sure what the actual problem is here; the VirtualizingStackPanel
is still in the visual tree, but it seems that none of the items actually added. Enough of the bad news, the good news is I've found a way to work round it, by changing the default style of the ScrollViewer
to place the header there instead, which results in two styles that look like this:
<Style x:Key="ScrollViewerStyle1" TargetType="ScrollViewer">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="VerticalScrollBar"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="HorizontalScrollBar"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Header" Style="{StaticResource PhoneTextLargeStyle}"/>
<ScrollContentPresenter x:Name="ScrollContentPresenter"
Grid.Row="1"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<ScrollBar x:Name="VerticalScrollBar"
Grid.RowSpan="2"
IsHitTestVisible="False"
Opacity="0"
Height="Auto"
Width="5"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0"
Value="{TemplateBinding VerticalOffset}"
Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}" />
<ScrollBar x:Name="HorizontalScrollBar"
Grid.RowSpan="2"
IsHitTestVisible="False"
Opacity="0"
Width="Auto"
Height="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableWidth}"
Minimum="0"
Value="{TemplateBinding HorizontalOffset}"
Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxStyle2" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer x:Name="ScrollViewer"
Grid.Row="1"
Style="{StaticResource ScrollViewerStyle1}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
来源:https://stackoverflow.com/questions/4770892/adding-a-header-to-a-listboxs-scrollviewer-and-keeping-the-virtualizingstackpan