Reputation: 7654
I've made a nice little three-item wide list of tiles that work as switches. It looks something like this:
Looking good huh? Well, I have about 130 of these tiles in a vertically scrolling list, and it takes ages to load. According to the performance analysis tool, each element takes about 18ms to render - which gives me about a 2.3 second rendering time. On the device, it's often twice that time. This wouldn't really be a crisis, but the UI is totally black and unresponsive up until these elements have been drawn.
After some research online, I realized this is because the WrapPanel
control from the toolkit doesn't virtualize its items - thus making the GPU
render all objects at once (using up a lot of memory in the process).
Now, are there any ways to make this go faster?
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>
The ListBox
's ItemsSource is set in the codebehind - if you wondered.
Upvotes: 3
Views: 1115
Reputation: 61
A few ideas which might be helpful:
Upvotes: 1
Reputation: 4081
Well, if you populate the listbox asynchronously from another thread, you can avoid the unresponsive 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; }
}
Upvotes: 3