Pergunta

Estou usando um ListView para mostrar itens em uma lista. O usuário pode selecionar os itens ou usar algumas 'teclas pré -selecionadas' para selecionar itens com atributos especificados.

Para verificar os itens, uso algo assim:

for(int i;i<MyListView.Items.Count;++i)
{
    if( /*... Check if the items should be selected ...*/ )
        (MyListView.ItemContainerGenerator.ContainerFromIndex(i) as ListViewItem).IsSelected = true;
}

Isso funciona perfeitamente para itens, que são visíveis no momento da excitação. Mas, para itens, que não são visíveis, o contêinerFromIndex () retorna nulo. Ouvi dizer que isso tem algo a ver com virtualização e que a lista não sabe sobre os itens vizinhos ou desvantagens do 'campo de visão'. Mas como é que é possível ter itens selecionados na lista fora do 'campo de visão' quando você os seleciona manualmente?

E como fazer uma seleção de um item fora do 'campo de visão'? Eu acho que isso deve ser possível.

Obrigado por qualquer ajuda, marcas

Foi útil?

Solução

Como você mencionou, meu palpite é que o problema é a virtualização dos itens da ListView. Por padrão, ListView (e ListBox) Use VirtualizingStackPanel como itemspanel para melhorar o desempenho. Uma breve explicação de como funciona pode ser lida aqui.

Você pode substituir outro painel, no entanto. Nesse caso, tente usar um Stackpanel normal. Se você tiver uma tonelada de itens no ListView, especialmente se forem itens complexos, o desempenho poderá sofrer um pouco.

<ListView>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

Editar

Você também pode tentar a solução descrita Nesta pergunta semelhante, dependendo do seu modelo. No entanto, isso provavelmente não funcionará para você.

Outras dicas

Ao lidar com os controles virtuais de itens, uma alternativa para desativar a virtualização (que é de fato um recurso útil às vezes, mesmo que interfira na operação correta de outras partes da API), é encontrar o VirtualizingPanel e diga explicitamente para rolar.

Por exemplo:

void ScrollToIndex(ListBox listBox, int index)
{
    VirtualizingPanel panel = FindVisualChild<VirtualizingPanel>(listBox);

    panel.BringIndexIntoViewPublic(index);
}

static T FindVisualChild<T>(DependencyObject o) where T : class
{
    T result = o as T;

    if (result != null)
    {
        return result;
    }

    int childCount = VisualTreeHelper.GetChildrenCount(o);

    for (int i = 0; i < childCount; i++)
    {
        result = FindVisualChild<T>(VisualTreeHelper.GetChild(o, i));

        if (result != null)
        {
            return result;
        }
    }

    return null;
}

Não estou muito feliz com a necessidade de pesquisar na árvore visual para encontrar o painel, mas não estou ciente de nenhuma outra maneira de obtê -la, nem rolar para um índice específico ao lidar com um painel virtualizador.

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