In my WP8 app I use Background Transfer Sevice and LongListSelector
with ProgressBar
as it's DataTemplate
to display items download progress to user. The problem is that ProgressBar
does not show real progress but keeps jumping back and forth.
Here's my XAML. LongListSelector
periodically recieves a list of BackgroundTransferRequest
's and uses
ProgressBar
to display them:
<phone:LongListSelector IsGroupingEnabled="False" x:Name="Views">
<phone:LongListSelector.ListHeader>
<StackPanel Style="{StaticResource M20}">
<controls:TextTile Txt="Cancel downloads" Sign="x" Tap="CancelDownloads" />
</StackPanel>
</phone:LongListSelector.ListHeader>
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<ProgressBar Maximum="{Binding TotalBytesToReceive}" Value="{Binding BytesReceived}" Minimum="0" />
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
LongListSelector
gets updated periodically from code behind class:
Views.ItemsSource = BackgroundTransferService.Requests.ToList()
This issue happens in LongListSelector
only in case if more than one item is displayed. Everything works fine If I try to use ListBox
for example. Why is this thing happening and what should I do to fix it?
I couldn't fit this in a comment -- try this:
public class BackgroundTransferRequestWrapper : INotifyPropertyChanged {
private BackgroundTransferRequest _request;
public BackgroundTransferRequestWrapper(BackgroundTransferRequest request) {
_request = request;
_request.TransferProgressChanged += OnTransferProgressChanged;
}
private void OnTransferProgressChanged(object sender, BackgroundTransferEventArgs e) {
BytesReceived = _request.BytesReceived;
TotalBytesToReceive = _request.TotalBytesToReceive;
}
private long bytesReceived = 0;
public long BytesReceived {
get { return bytesReceived; }
set {
bytesReceived = value;
OnPropertyChanged();
}
}
private long totalBytesToReceive = 0;
public long TotalBytesToReceive {
get { return totalBytesToReceive; }
set { totalBytesToReceive = value;
OnPropertyChanged();}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Instead of resetting the ItemsSource on a timer, instead just do this:
foreach (var request in BackgroundTransferService.Requests) {
Requests.Add(new BackgroundTransferRequestWrapper(request));
}
In this example, Requests is an ObservableCollection bound to your ItemsSource. With this you shouldn't need to update manually at all -- the BackgroundTransferRequest events will drive the wrapper to notify prop changes as they happen.
I didn't test your example fully, but I suspect your issue has something to do with LongListSelector's UI virtualization and the way you're constantly resetting ItemsSource. Another possibility is the order of the requests might change every time you get them from BackgroundTransferService.
Good luck!