Pergunta

Eu tenho uma caixa de listagem e ela está vinculada a uma lista de objetos simples.Como sabemos, a caixa de listagem por padrão tem seu host de itens como um Stackpanel e, portanto, apresenta os itens desta maneira

item1
item2
item3
item4
item5
item6

No entanto, tenho algumas condições pelas quais verifico se o item deve ser exibido horizontal ou verticalmente e, portanto, os itens podem ser dispostos desta forma

Ex: -

item1
item2
item3 item4 item 5
item6

Como é possível fazer isso?

(Se você está se perguntando por que eu precisaria de tal coisa, um cenário de exemplo seria "atualizações de estilo do Facebook" onde se um usuário carrega 3-4 fotos continuamente, elas nem sempre aparecem na próxima linha, mas podemaparecem horizontalmente, ao passo que se ele postar algum evento, ele aparecerá na próxima linha.)

Agradecemos antecipadamente :)

Foi útil?

Solução

Os fundamentos da solução é usar outro ItemsControl no ItemTemplate do ListBox.Este ItemsControl deve ter um StackPanel orientado horizontalmente como seu ItemsPanel.

Aqui está um exemplo básico.Vamos começar com alguns dados de teste muito simples: -

public class TestStringList : List<string>
{
    public TestStringList()
    {
        AddRange(new[] {"Anthony", "Kar", "Martin", "Jon", "Erik", "Darin",
            "Balus", "Mike", "Hans", "Alex", "Anomie", "David" });

    }
}

Agora queremos exibir esta lista em uma ListBox, mas manter todos os nomes que têm a mesma inicial na mesma linha.Vou usar uma implementação de IValueConverter para lidar com o agrupamento de que precisamos.Se você estiver usando MVVM, então você faria seu ViewModel tirar isso.

public class Grouper : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((IEnumerable<string>)value).OrderBy(s => s).GroupBy(s => s[0]);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

A saída deste conversor é basicamente IEnumerable<IEnumerable<string>>, que é o que queremos.O ListBox externo enumera o conjunto externo e o ItemsControl interno enumera o conjunto interno de strings que será um conjunto de nomes com a mesma inicial.

Aqui está o xaml: -

<UserControl x:Class="SilverlightApplication1.SimpleGrouping"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <local:TestStringList x:Key="TestData" />
        <local:Grouper x:Key="grouper" />
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox ItemsSource="{Binding Converter={StaticResource grouper}, Source={StaticResource TestData}}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal" />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" Margin="5" />
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

Outras dicas

Se estiver usando o MVVM padrão eu faria algo assim:

  1. Crie um ViewModel para a visualização em que sua caixa de listagem está. Esta VM contém uma coleção de instâncias ListItemViewModel (consulte o próximo ponto)
  2. Crie um ViewModel chamado ListItemViewModel (dê a ele um nome mais apropriado, com base em seu domínio). Este modelo de visualização contém uma coleção de instâncias ItemViewModel (consulte o próximo ponto).
  3. Crie um ViewModel chamado ItemViewModel. Cada um deles apóia um único item da lista. Dê a este um nome mais apropriado com base no seu domínio.
  4. Crie uma visualização que contenha sua caixa de listagem. Vincule sua caixa de listagem à coleção de ListItemViewModels na VM. O modelo de item para esta caixa de listagem será um ListItemView (consulte o próximo ponto). O modelo do painel de itens será o StackPanel padrão.
  5. Crie um ListItemView que tenha um contexto de dados ListItemViewModel. Esta visualização consiste em um StackPanel horizontal de ItemViews (veja o próximo ponto).
  6. Crie um ItemView que é apoiado pelo ItemViewModel.

Sua visualização seria mais ou menos assim, cada uma com um ViewModel correspondente.

Como eu disse acima, você definitivamente vai querer mudar o nome de suas visualizações / modelos de visualização, os meus são apenas para fins de demonstração :)

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