在 Windows 8 Metro 应用程序中,是否可以创建一个 ScrollViewer,在到达视图中的最后一项时,它会循环回视图中的第一项?如果是这样,我怎样才能达到这个效果?
2 回答
这绝对是可能的。我目前正在解决问题,完成后会发布工作。到目前为止,它类似于下面。
这个想法是你钩入滚动查看器的 viewchanged 事件,该事件在你移动栏时触发。到达那里后,计算您在偏移中的位置和项目的大小,然后您可以使用它来衡量列表框容器的实际大小或您拥有的东西。
一旦您知道您在偏移量中的位置并知道列表框的实际高度和项目的高度,您就知道哪些项目当前可见,哪些不可见。确保绑定到对象的列表是一个可观察的集合,该集合实现了具有双向绑定的 INotifyChanged 接口。然后,您可以定义一组对象,以根据您所在的滚动位置来回旋转。
另一种选择是尝试不同的起点,也许是一个带有选取框和滚动条的控件?
XAML
</UserControl.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="ScrollViewer1">
<ListBox x:Name="SampleListBox" Background="White" ItemsSource="{Binding Path=sampleItems}" ItemTemplate="{StaticResource sampleTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="0" Grid.RowSpan="2">
</ListBox>
</ScrollViewer>
</Grid>
代码背后
public sealed partial class MainPage : Page
{
List<SampleItem> sampleItems;
const int numItems = 15;
public MainPage()
{
sampleItems = new List<SampleItem>();
for (int i = 0; i < numItems; i++)
{
sampleItems.Add(new SampleItem(i));
}
this.InitializeComponent();
SampleListBox.ItemsSource = sampleItems;
ScrollViewer1.ViewChanged += ScrollViewer1_ViewChanged;
}
void ScrollViewer1_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer viewer = sender as ScrollViewer;
ListBox box = viewer.Content as ListBox;
ListBoxItem lbi = box.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
double elementSize;
if (lbi == null)
return;
elementSize = lbi.ActualHeight;
} /// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
public class SampleItem
{
public String ItemCount { get; set; }
public SampleItem(int itemCount)
{
ItemCount = itemCount.ToString();
}
}
我不相信在 WinRT/XAML 中有这样的控件,因此您需要实现自定义控件。您可以采用许多方法,但我可能会避免使用 ScrollViewer 并直接处理操作事件,因为将 ScrollViewer 的行为转变为您的要求可能并不容易。我会根据操作事件和滚动偏移来控制滚动偏移——在视图中定位元素——例如使用 Canvas 控件。您需要根据滚动偏移量重新定位项目面板中的元素,以便例如超出一端的视口的项目移动到另一端。这将涉及自定义依赖属性、项目容器等。如果您了解所有这些 API,可能至少需要几个小时的工作。