我做了一个很好的小三项宽的瓷砖列表,作为开关。它看起来像这样:
好望啊?好吧,我在垂直滚动列表中有大约130个这样的图块,加载需要很长时间。根据性能分析工具,每个元素需要大约18ms来渲染 - 这给了我大约2.3秒的渲染时间。在设备上,通常是两倍的时间。这不会是一场危机,但在这些元素被绘制之前,用户界面完全是黑色的,没有反应。
经过一些在线研究后,我意识到这是因为工具包中的WrapPanel
控件没有虚拟化其项目 - 从而使GPU
一次渲染所有对象(占用大量内存)进行中)。
现在,有没有办法让这个更快?
XAML:
<ListBox x:Name="ChannelsListBox" Grid.Row="2" Margin="0,40,0,0">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="ChannelTile" Margin="6,6,6,6" Tap="ChannelTile_Tap">
<!-- context menu code removed -->
<Rectangle Width="136" Height="136" Fill="{StaticResource LightGrayColor}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ListBox
的ItemsSource在代码隐藏中设置 - 如果你想知道的话。
答案 0 :(得分:3)
好吧,如果您从另一个线程异步填充列表框,则可以避免无响应的UI。
EDITED2:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
/* In the xaml code:
<ListBox x:Name="ChannelsListBox" ItemsSource="{Binding ListOfTestClasses}" ...
*/
var vm = new MainPageViewModel();
DataContext = vm;
vm.StartLoadingDataAsync(10000);
}
}
public class MainPageViewModel
{
public ObservableCollection<TestClass> ListOfTestClasses { get; set; }
private BackgroundWorker workerThread;
public MainPageViewModel()
{
ListOfTestClasses = new ObservableCollection<TestClass>();
workerThread = new BackgroundWorker();
workerThread.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e) =>
{
for (int i = 0; i < (int)e.Argument; i++)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
ListOfTestClasses.Add(new TestClass { Text = "Element " + (i + 1) });
});
Thread.Sleep(150);
}
});
}
public void StartLoadingDataAsync(int numberOfElements)
{
workerThread.RunWorkerAsync(numberOfElements);
}
}
public class TestClass
{
public string Text { get; set; }
}
答案 1 :(得分:1)
一些可能有用的想法: