Silverlight - 添加到列表框的每个项目之间的延迟

时间:2011-04-19 13:50:35

标签: silverlight silverlight-4.0

当我将一个项目添加到我的列表框时,我有一些很好的动画显示淡入。我认为在每个添加的项目之间稍微延迟可能会很酷,因此在添加所有项目时会有一个很好的级联扫描(LB使用水平StackPanel)。因为我永远不会有结果集>这10件事对我来说似乎并不太糟糕。

问题是,列表框不会在每次添加后添加项目,而是等到我的方法完成后再显示所有新项目。因此,对于下面的(夸大)示例,我的页面会冻结10秒钟,然后显示所有10个项目。

    private void bookItemsLoaded(DownloadStringCompletedEventArgs e) {
        BookResults.Clear();
        foreach (AmazonTitleSearchResultDTO item in BookItemDTOLoader.LoadObjects(e.Result)) {
            BookResults.Add(new AmazonExplorerBookItemViewModel() { ImageURL = item.CoverURL, Title = item.Title, ASIN = item.ASIN });
            Thread.Sleep(1000);
        }
    }

如何让Silverlight每秒显示一个项目? (是的,我知道这将是一种令人难以忍受的用户体验。真正的延迟会小很多)

[以下是显示如何进行LB项目动画的文章的link,尽管大多数阅读此内容的人可能已经看过它了

修改

下面的答案是完美的,但这是一个稍微简单的版本,没有递归。

//get all the items to add into a local, tmeporary list, and call this method:
private void AddBookToResults(List<AmazonTitleSearchResultDTO> bookList)
{    
    DispatcherTimer Timer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 1) };
    int index = 0;

    Timer.Tick += (s, e) => {
        ItemCollection.Add(temp[index++]);
        if (index == temp.Count)
            Timer.Stop();
    };
    Timer.Start();
}

1 个答案:

答案 0 :(得分:3)

问题是您的整个计算都是在主线程上进行的,并且在您的方法完成之前,实际的UI动画不会发生,并且会为UI绘图代码提供再次运行的机会。这就是为什么所有的动画都“同时”发生的原因,即使你在添加每个动画后等待。如果你想避免这种情况,你需要将循环编程为一系列委托以在主线程上运行。

private void bookItemsLoaded(DownloadStringCompletedEventArgs e) {
    BookResults.Clear();
    var bookList = BookItemDTOLoader.LoadObjects(e.Result).ToList();
    AddBookToResults(bookList, 0);
}

private void AddBookToResults(List<AmazonTitleSearchResultDTO> bookList, int index)
{
    if (index == bookList.Count) {
        return;
    }

    var item = bookList[index];
    BookResults.Add(new AmazonExplorerBookItemViewModel() { ImageURL = item.CoverURL, Title = item.Title, ASIN = item.ASIN });

    var timer = new DispatcherTimer();
    timer.Interval = new TimeSpan(0, 0, 1);
    timer.Tick += () => {
        timer.Stop();
        AddBookToResults(bookList, index + 1);
    };
    timer.Start();
}

另一种解决方案是让循环在后台线程上运行。这不如单线程委托版本可靠,但代码也少,而且可能更容易理解。