Pergunta

eu tenho um ObservableCollection de viewmodels que estão sentados em um WPF DataGrid. o DataGrid tem três colunas:

  • Coluna de posição; Isso é renderizado em tempo de execução por um UserControl que exibe a posição da linha no meu datagrid
  • Coluna de nome; Isso é renderizado no tempo de execução por um UserControl que exibe o nome da coluna (sim, eu preciso de um UserControl para isso com base em como o nome precisa ser exibido, mas isso é um aparte)
  • Coluna de dados; Isso é renderizado em tempo de execução por mais um UserControl.

Minhas colunas são definidas assim:

        <toolkit:DataGrid.Columns>
            <toolkit:DataGridTemplateColumn Header="" MinWidth="35" MaxWidth="35" SortMemberPath="Position.PositionIndex" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Position}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Name" MinWidth="150" Width="150" SortMemberPath="Name" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Name}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Data" Width="Auto" CanUserSort="False">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Data}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
        </toolkit:DataGrid.Columns>

Então, porque minhas colunas de linha e nomes são UserControls, o WPF DataGrid não pode classificá -los nativamente. Então, para facilitar a classificação, quando um cabeçalho de coluna é clicado, eu faço alguns ListCollectionView.CustomSort Magia.

Aqui está a aparência dos meus classificadores personalizados para a coluna de nome:

// Customized sorter, by name, ascending.
public class AscendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return lhs.Name.CompareTo(rhs.Name);
    }
}

// Customized sorter, by name, descending.
public class DescendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return rhs.Name.CompareTo(lhs.Name);
    }
}

O problema é que isso é Incrivelmente lento. Não consigo descobrir o porquê. Com 10 itens no DataGrid, meu aplicativo interrompe por 3-4 segundos enquanto ele recorre. Eu pensei ListCollectionView.CustomSort era para ser a maneira mais eficiente de classificar um ObservableCollection... Onde eu estou errando?

Foi útil?

Solução

O WPF está recriando todos os seus seus controlos de userControla toda vez que o tipo muda, então meu palpite é que algo na construção desses controles é lento. Mas isso é apenas um palpite.

Você deve começar restringindo o problema. Aqui estão algumas etapas que você pode tomar:

  1. Descubra qual operação está levando 3-4 segundos. Você não declarou se o atraso acontece apenas ao atribuir o valor ao alfabetizado ou sempre que a lista muda após a alfabetização ter sido definida. Isso faz a diferença.

  2. Tente adicionar uma coluna de texto regular e classificá-la usando o tipo interno para ver se é rápido ou não. Talvez você já tenha feito isso, mas não disse em sua pergunta.

  3. Para fins de diagnóstico, pare temporariamente de definir alfabearsort e defina listCollectionView.Filter. Defina -o como um filtro que sempre retorna true. Se você ainda tiver a desaceleração, o problema estará relacionado à tentativa do ListCollectionView de reorganizar itens.

  4. Edite temporariamente seus modelos e substitua seus controlos personalizados por algo trivial (por exemplo <CheckBox/>) para ver se as coisas aceleram ou não.

  5. Defina pontos de interrupção nos construtores de seus userControls para ver se eles estão sendo chamados de número de vezes esperado (ou seja, 10 chamadas de construtor se houver 10 itens na lista). Se eles estiverem sendo chamados mais vezes do que o esperado, olhe para os traços de pilha para ver de onde vêm as chamadas extras.

  6. Adicione o código aos seus construtores UserControl para escrever o DateTime. Agora, os construtores foram chamados para a janela de saída (ou um log, ou qualquer outra coisa). Isso lhe dará uma ideia quanto tempo cada um está demorando.

  7. Adicione várias centenas de itens à sua observação ObservableCollection, execute o aplicativo lado a lado com o vs.net, clique no botão de classificação (ou o que for) e pressione o botão Break All no vs.net e olhe para o rastreamento da pilha. Bata Continue e bata imediatamente o Break All novamente, depois olhe para o rastreamento da pilha novamente. Repita muitas vezes. Isso lhe dará uma boa idéia do que está demorando o tempo extra.

Se, como eu suspeito, o problema for lento a criação e a ligação da UserControls, você encontrará: o problema acontece em cada mudança de lista e também acontece quando você muda o filtro, as coisas aceleram quando você substitui seus controlos de UserCons por <CheckBox/>, seu construtor só será chamado uma vez por item, o tempo entre as chamadas será generoso.

Observe que não estou dizendo que é o construtor Dos UserControls que são lentos-pode ser que o UserControl instancie muitos subobjetos quando está ligado a dados ou que inclua objetos lentos ou complexos, um subobjetivo carrega um arquivo ou muitas outras causas possíveis. A linha inferior é que instanciando o datatemplate no objeto e adicioná -lo à árvore visual está fazendo algo lento. Os traços de pilha devem dar uma idéia para onde procurar.

Se for algo mais ou você não conseguir descobrir, basta atualizar sua pergunta para fornecer mais informações sobre o que os testes acima revelaram e tentaremos ajudá -lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top