【发布时间】:2010-03-13 19:48:27
【问题描述】:
【问题讨论】:
-
深灰色、浅灰色、深灰色、浅灰色
-
我真的很喜欢这种风格!您可以通过任何方式将其发布到 pastebin.com 并将链接发送给我。
【问题讨论】:
是的,WPF 提供了一种相当优雅的方式来实现这一点,因为它的模板机制允许你用你喜欢的任何东西填充 GridView 中未使用的区域。
您需要做的就是修改ListView 模板以使用VisualBrush 绘制未使用的部分,该VisualBrush 通常由垂直堆叠的两个GridViewItems 组成(在一般情况下它将是AlternationCount @987654326 @)。
唯一的复杂性是在绘制ScrollViewer 的未使用部分时选择从哪种颜色开始。这计算为 Items.Count 模 AlternationCount。解决方案是创建一个简单的Control 来执行此计算并在我们的ListView 模板中使用它。为了便于解释,我将控件称为“ContinueAlternation”。
ListView 模板主要是默认模板,使用DockPanel 在ScrollViewer 下方添加local:ContinueAlternation 控件,如下所示:
<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,并绘制有平铺的 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 将是在给定AlternationCount 和ItemsCount 的代码隐藏中生成的虚拟ListViewItem 数组:
public class ContinueAlternation
{
public Style ItemsContainerStyle ... // Declare as DependencyProperty using propdp snippet
public int AlternationCount ... // Declare as DependencyProperty using propdp snippet
public int ItemsCount ... // Declare as DependencyProperty using propdp snippet
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if(e.Property==ItemsContainerStyleProperty ||
e.Property==AlternationCountProperty ||
e.Property==ItemsCountProperty)
{
// Here is where we build the items for display
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 ... // Declare as DependencyProperty using propdp snippet
}
请注意,同样的代码可以用PropertyChangedCallback 代替OnPropertyChanged。
您还需要做一些事情来确保空白行是所需的高度。最简单的方法是在ItemsContainerStyle 中设置MinHeight 或Content。或者ContinueAlternation 可以在构造每个ListViewItem 时设置高度。
我在脑海中输入了所有这些代码,但它与我之前编写和使用过的代码相似,因此它应该基本上可以正常工作。
【讨论】: