문제

MVVM을 사용하여 WPF 앱을 구축하고 있습니다. 다음과 같이 뷰 모델이 게으른로드를 사용합니다.

public class AssignmentsViewModel
{

    List<AssignmentViewModel> _Assignments;
    public List<AssignmentViewModel> Assignments
    {
        get
        {
            if (_Assignments == null)
                _Assignments = new List<AssignmentViewModel>(Data.GetAssignments());
            return _Assignments;
        }
        set { _Assignments = value; }
    }
}
public class AssignmentViewModel
{
    List<NoteViewModel> _Notes;
    public List<NoteViewModel> Notes
    {
        get
        {
            if (_Notes == null)
                _Notes = new List<NoteViewModel>(Data.GetNotes());
            return _Notes;
        }
        set { _Notes = value; }
    }
}

보기에는 ListView의 할당 뷰 모델과 DataTemplate의 ListBox에 메모가 있습니다.

160 개의 항목이있는 할당 ViewModels 중 하나를 표시하면로드하는 데 1000ms가 걸립니다. 나는 그것이 150 만 행의 데이터베이스 테이블에서 잡는 노트 속성 때문이라고 생각했다. 나는 그것을 확인했고 메모 목록을 채우는 데 60ms 만 필요했습니다. 그래서 나는 그것이 160 개의 항목을 ListBox에로드하는 데이터베이닝이라고 생각합니다. 그러나 Listboxes가 콘텐츠를 가상화하기 때문에 그렇지 않아야합니다 (나는 스누핑하고 항목이 가상화 스택 패널에 있음을 확인했습니다).

그래서 나는 손실에있다. 나는 추가 940ms를 섭취하는 것이 무엇인지 알아내는 방법을 모른다.

이것을 추적하려면 어떻게해야합니까? 성능이 핵심이며 개선 방법을 모르겠습니다.

도움이 되었습니까?

해결책

UI가 무엇인지 알지 못하면 UI의 무언가가 비트 모프 펙트의 큰 사용으로 속도를 늦출 가능성이 있습니다.

또한 목록을 ObservAbleCollection으로 전환 할 수 있습니다. 그것에 대한 바인딩은 목록보다 훨씬 빠를 수 있습니다..

좋은 것도 있습니다 성능 프로파일 링 도움이 될 수있는 도구.

다른 팁

XAML을 볼 수 있습니까?

StackPanel (또는 유사한 컨트롤) 안에 ListBox가있는 경우 ListBox는 항목을 가상화하지 않습니다.

이것은 가상화됩니다 :

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Label Grid.Row=0>Your label here</Label>
  <ListBox Grid.Row=1 Your properties here... />

</Grid>

이것은 그렇지 않을 것입니다 :

<StackPanel>
  <Label>Your label here</Label>
  <ListBox Your properties here... />
</StackPanel>

StackPanel 내부에서 ListBox는 최대 높이로 렌더링하고 스크롤을 위해 StackPanel에 따라 다릅니다. (가상화 없음)

그리드 내부에서 Listbox는 그리드 행 높이로 렌더링하고 자체 스크롤 뷰어를 사용합니다. (가상화)

또한 그리드 내부에 넣는 대신 ListBox에서 높이 또는 최대 높이의 속성을 설정할 수 있지만 StackPanel을 사용하는 경우 어떤 종류의 자동화를 원한다고 생각합니다.

스택 패널을 그리드 내부에 넣어 속임수를 쓰지 않아도됩니다. ListBox는 어딘가에서 최대 높이를 도출 할 수 있어야합니다.

게으른 로딩과 함께 Perf-Testing을 시도 했습니까?

또한 항목에 대한 데이터 emplates/뷰는 얼마나 복잡합니까? 간단한 텍스트 블록 표현이있는 테스트를 실행하여 뷰가 얼마나 복잡하지 않은지 확인하십시오.

SQL을 다시 한 번 살펴보고 컬렉션이 채워 지는지 확인합니다. L2는 결과를 열거 할 때까지 실제로 채워지지 않습니다.

private IEnumerable<Thing> Method1()
{
    return _db.Things.Where(t => t.ID > 500);
}
private void Method2()
{
    var things = Method1(); // here, 'things' doesn't really contain anything
                            // even though you've already done the db fetch
    foreach (var thing in things) // 'things' gets populated here.
    {
        // do something
    }
}

예 : 전화 .ToList() 데이터가 반환 된 직후. 비즈니스 또는 UI 계층까지는 발생하지 않았을 수있는 데이터 계층에서 더 많은 활동이 보입니다.

나는 그것을 알아. 텍스트 트래핑이 때때로 꽤 크기 때문에 텍스트 블록이 필요했습니다. 데이터 emplate 내부의 너비를 명시 적으로 설정하고 어떤 이유로 목록 상자 내부의 가상화 택시 패널이 목록의 모든 항목을 실현하게하는 이유가 있습니다. 나는 그것을 그렇게 같은 그리드에 맞추기 위해 그것을 재 작업했다 ..

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
       ....
    </Grid>
    <ListBox Grid.Column="1" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
       ...//DataTemplate
    </ListBox>
</Grid>

이로 인해 Listbox가 빠르게로드되었습니다. 답변 해 주셔서 감사합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top