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

Silverlight-添加到列表框的每个项目之间的延迟,silverlight,silverlight-4.0,Silverlight,Silverlight 4.0,我有一些很好的动画,当我将一个项目添加到我的列表框时,它们会显示淡入。我认为在添加的每个项目之间稍微延迟一点可能会很酷,所以在添加所有项目时会有一个很好的级联扫描(LB使用水平堆叠面板)。因为我永远不会有一个结果集>10项,这对我来说似乎并不太糟糕 问题是,列表框不会在每次添加后添加项目,而是等待我的方法完成,然后整体显示所有新项目。因此,对于下面的(夸张的)示例,我的页面冻结了10秒钟,然后所有10个项目都显示出来 private void bookItemsLoaded(Downlo

我有一些很好的动画,当我将一个项目添加到我的列表框时,它们会显示淡入。我认为在添加的每个项目之间稍微延迟一点可能会很酷,所以在添加所有项目时会有一个很好的级联扫描(LB使用水平堆叠面板)。因为我永远不会有一个结果集>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项目动画的文章的结尾,尽管大多数阅读本文的人可能已经看过了]

编辑

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

//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();
}
//获取要添加到本地tmeporary列表中的所有项目,并调用此方法:
私有无效AddBookToResults(列表bookList)
{    
Dispatchermer Timer=new dispatchermer(){Interval=new TimeSpan(0,0,1)};
int指数=0;
计时器.勾号+=(s,e)=>{
ItemCollection.Add(temp[index++]);
如果(索引==临时计数)
Timer.Stop();
};
Timer.Start();
}

问题在于,整个计算都在主线程上进行,而实际的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();
}
private void bookItemsLoaded(下载StringCompletedEventArgs e){
BookResults.Clear();
var bookList=BookItemDTOLoader.LoadObjects(e.Result.ToList();
AddBookToResults(图书列表,0);
}
私有void AddBookToResults(列表bookList,int索引)
{
if(index==bookList.Count){
返回;
}
var项目=账簿列表[索引];
添加(新的AmazonExplorerBookItemViewModel(){ImageURL=item.CoverURL,Title=item.Title,ASIN=item.ASIN});
var timer=newdispatchermer();
timer.Interval=新的时间跨度(0,0,1);
timer.Tick+=()=>{
timer.Stop();
AddBookToResults(图书列表,索引+1);
};
timer.Start();
}

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

我希望我能给出+1以上的值并接受它。这很好-我用更少的代码编写了一个类似的版本,作为编辑。再次感谢-我仍然被你在那里抛出的递归所吸引-你是一个偶然的老LISP程序员吗??:)@亚当,我从来没有编写过LISP,但即使没有这个障碍,我也从来没有遇到过我不喜欢的递归。@Adam,P.S.:我非常喜欢你的修订版——它实际上比我的更清晰、更高效。做得好!谢谢你,先生。谢谢你帮助我理解这个问题。如果这不是一个如此深奥的问题,你可能会得到更多的赞成票:)