如果您有时间,请创建一个新的空白应用(XAML)模板并编写以下XAML代码。
我认为创建 WPF应用程序是没用的,因为它看起来好像容器回收不起作用。此外, GridView 必须替换为 ListView 。
<Page.Resources>
<vm:MainViewModel x:Key="Main" />
</Page.Resources>
<Page.DataContext>
<Binding Source="{StaticResource Main}" />
</Page.DataContext>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
VerticalAlignment="Center">
<Grid.Resources>
<Style x:Key="GridViewStyle1"
TargetType="GridView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridView">
<ScrollViewer HorizontalSnapPointsAlignment="Near"
HorizontalSnapPointsType="MandatorySingle">
<ItemsPresenter VirtualizingStackPanel.VirtualizationMode="Standard" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<GridView Style="{StaticResource GridViewStyle1}"
ItemsSource="{Binding Items}"
SelectionMode="None">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Loaded="StackPanel_Loaded">
<Grid Width="800"
Height="400">
<ScrollViewer HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Visible">
<Border Background="#b7d84b">
<TextBlock Foreground="Black"
Text="{Binding Message}" />
</Border>
</ScrollViewer>
</Grid>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
创建视图模型和项类:
public class MainViewModel
{
private const int NumberOfItems = 10000;
public ObservableCollection<Item> Items
{
get;
private set;
}
public MainViewModel()
{
var tempCollection = new ObservableCollection<Item>();
for (var index = 0; index < NumberOfItems; ++index)
{
var item = new Item
{
Id = index,
Message = GetMessage(index)
};
tempCollection.Add(item);
}
Items = tempCollection;
}
private string GetMessage(int index)
{
var sb = new StringBuilder();
for(var i = 0; i < 100; ++i)
{
sb.Append("...\n");
}
sb.Append("This is item #");
sb.Append(index);
return sb.ToString();
}
}
public class Item
{
public string Message { get; set; }
public int Id { get; set; }
}
启动应用程序时,您可以滚动浏览一系列项目。我注意到当您垂直滚动特定项目以便可以看到“这是项目#x”消息时,您将在向右滚动后再次看到另一条消息“这是项目#x”(尽管您没有滚动垂直的项目。)
这是因为项目是虚拟化的。当项目变为现实时,从池中使用容器。如果你运气不好,容器已经滚动了......
池中有10个项目:
文件背后的代码:
private readonly DateTime _start;
public MainPage()
{
this.InitializeComponent();
_start = DateTime.Now;
}
[Conditional("DEBUG")]
public void WriteDebugMessage(string message)
{
var span = DateTime.Now - _start;
Debug.WriteLine(
"{0:D2}:{1:D2}:{2:D3} - {3}",
span.Minutes,
span.Seconds,
span.Milliseconds,
message);
}
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
WriteDebugMessage("StackPanel loaded.");
}
接下来,我重新设计ItemsPresenter对象:
<ItemsPresenter VirtualizingStackPanel.VirtualizationMode="Standard"/>
如果有效,则无法提高效果。
有谁知道这个问题的优雅解决方案?由于公共领域太多,我不想被解雇;)我也想过写一个附属物......
答案 0 :(得分:0)
已更新:
我仍然不知道为什么
<ItemsPresenter VirtualizingStackPanel.VirtualizationMode="Standard"/>
不起作用。所以我的最新解决方案是黑客攻击。此外,尽管您已经垂直滚动,但向左滚动可能会显示放回的项目。我在MainPage.xaml.cs中使用附加属性来定义每个垂直 ScrollViewer 的垂直偏移量:
public static double GetVerticalOffset(DependencyObject obj)
{
return (double)obj.GetValue(VerticalOffsetProperty);
}
public static void SetVerticalOffset(DependencyObject obj, double value)
{
obj.SetValue(VerticalOffsetProperty, value);
}
public static readonly DependencyProperty VerticalOffsetProperty =
DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(MainPage), new PropertyMetadata(-1.0, OnVerticalOffsetPropertyChanged));
private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var sv = d as ScrollViewer;
if (sv != null)
{
sv.ScrollToVerticalOffset((double) e.NewValue);
}
}
每次在数据虚拟化解决方案中请求特定项目的数据时,项目的 VerticalOffset 属性都将设置为0.由于默认值为-1,因此触发委托。