2011-04-19 2 views
3

내 목록 상자에 항목을 추가 할 때 페이드 인을 보여주는 멋진 애니메이션이 있습니다. 나는 추가 된 각 항목 사이에 약간의 지연을 두는 것이 좋을 것 같았습니다. 그래서 모든 항목이 추가 될 때 가로 건너서 멋진 캐스케이드 (LB는 가로 StackPanel 사용)가있을 것입니다. 나는 결과가 10 점 이상으로 나오지 않을 것이므로 나에게 그렇게 나쁘지는 않습니다.Silverlight - 목록 상자에 추가 된 각 항목 간의 지연

문제는 목록 상자가 각 추가 후에 항목을 추가하지 않지만 내 방법이 완료 될 때까지 기다린 다음 모든 새 항목을 한꺼번에 표시한다는 것입니다. 아래의 (과장된) 예를 들어 보면 내 페이지가 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); 
     } 
    } 

초당 하나의 항목을 표시하려면 어떻게해야합니까? (예, 나는 그것이 극심한 사용자 경험이 될 것이라는 것을 알고 있습니다. 실제 지연은 훨씬 더 작을 것입니다.)

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

답변

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

대체 솔루션은 백그라운드 스레드에서 루프를 실행하는 것입니다. 단일 스레드 대리자 버전보다 안정성이 떨어지지 만 코드가 적어 이해하기 쉽습니다.

+0

나는 +1 이상을주고 받아 들일 수 있으면 좋겠다. 괜찮습니다. 적은 코드로 비슷한 버전을 썼는데, 편집으로 던질 것입니다. –

+0

다시 한번 고마워요 - 당신이 저기에 던져 넣은 재귀와 함께 여전히 돌아 왔습니다 - 당신은 오래된 LISP 프로그래머입니까? :) –

+1

@ 아담, 나는 LISP를 결코 프로그래밍하지 못했지만 그 핸디캡이 없어도 나는 싫어하는 재귀를 만난 적이 없었다. –

관련 문제