当包含在LongListSelector中时,ProgressBar行为不正确

时间:2013-02-28 20:52:48

标签: xaml progress-bar windows-phone-8 longlistselector background-transfer

在我的WP8应用中,我使用后台转移服务和LongListSelector ProgressBar,因为它是DataTemplate,以向用户显示项目下载进度。问题是ProgressBar没有显示真正的进展,而是继续前后跳跃。

这是我的XAML。 LongListSelector会定期收到BackgroundTransferRequest的列表并使用 ProgressBar显示它们:

<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定期从类后面的代码更新:

Views.ItemsSource = BackgroundTransferService.Requests.ToList()

只有在显示多个项目的情况下才会在LongListSelector中发生此问题。一切正常如果我尝试使用ListBox例如。为什么会发生这种事情,我该怎么做才能解决它?

1 个答案:

答案 0 :(得分:1)

我无法在评论中说明这一点 - 试试这个:

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));
    }
}

而不是在计时器上重置ItemsSource,而只是这样做:

    foreach (var request in BackgroundTransferService.Requests) {
        Requests.Add(new BackgroundTransferRequestWrapper(request));
    }

在此示例中,请求是绑定到ItemsSource的ObservableCollection。有了这个,您根本不需要手动更新 - BackgroundTransferRequest事件将驱动包装器在它们发生时通知prop更改。

我没有完全测试您的示例,但我怀疑您的问题与LongListSelector的UI虚拟化以及您不断重置ItemsSource的方式有关。另一种可能性是每次从BackgroundTransferService获取请求时,请求的顺序可能会发生变化。

祝你好运!