Yes, WPF provides a pretty elegant way to implement this, because its template engine allows you to fill in an unused area GridViewwith whatever you like.
All you have to do is change the template ListViewto draw an unused section with VisualBrush, which usually consists of two GridViewItemsvertically stacked (in general it will be AlternationCount GridViewItems).
- , ScrollViewer. Items.Count AlternationCount. , Control, , ListView. "ContinueAlternation".
ListView, local:ContinueAlternation, ScrollViewer, DockPanel, :
<ControlTemplate TargetType="{x:Type ListView}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<DockPanel>
<ScrollViewer DockPanel.Dock="Top"
Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}"
Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="True" />
</ScrollViewer>
<local:ContinueAlternation
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
AlternationCount="{TemplateBinding AlternationCount}"
ItemsCount="{Binding Items.Count,
RelativeSource={RelativeSource TemplatedParent}}" />
</DockPanel>
</Border>
</ControlTemplate>
ContinueAlternation Rectangle, tiled VisualBrush, ItemsControl, , :
<ControlTemplate TargetType="{x:Type local:ContinueAlternation}">
<Rectangle>
<Rectangle.Fill>
<VisualBrush TileMode="Tile" Stretch="None"
ViewPortUnits="Absolute"
ViewPort="{TemplateBinding ViewportSize}">
<ItemsControl x:Name="PART_ItemsControl"
ItemsSource="{Binding}" />
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</ControlTemplate>
DataContext ListViewItem, AlternationCount ItemsCount:
public class ContinueAlternation
{
public Style ItemsContainerStyle ...
public int AlternationCount ...
public int ItemsCount ...
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if(e.Property==ItemsContainerStyleProperty ||
e.Property==AlternationCountProperty ||
e.Property==ItemsCountProperty)
{
DataContext =
from index in Enumerable.Range(ItemsCount,
ItemsCount + AlternationCount)
select BuildItem( index % AlternationCount);
}
}
ListViewItem BuildItem(int alternationIndex)
{
var item = new ListViewItem { Style = ItemsContainerStyle };
ItemsControl.SetAlternationIndex(item, alternationIndex);
return item;
}
protected override Size MeasureOverride(Size desiredSize)
{
var ic = (ItemsControl)GetTemplateChild("PART_ItemsControl");
ic.Width = desiredSize.Width;
Size result = base.MeasureOverride(desiredSize);
ViewportSize = new Size(ic.DesiredSize);
return result;
}
public Size ViewportSize ...
}
, PropertyChangedCallback OnPropertyChanged.
-, , - . - MinHeight Content ItemsContainerStyle. ContinueAlternation , ListViewItem.
, , , .