Question

J'ai une boîte de liste et elle est liée à une liste d'objets simples. Comme nous le savons, la liste de listbox a par défaut que ses articles sont hôte en tant que stackpanel et donc il présente des articles de cette façon

item1
item2
item3
item4
item5
item6

Cependant, j'ai des conditions dans lesquelles je vérifie si l'élément doit être affiché horizontalement ou verticalement et donc les articles pourraient être disposés de cette manière

Par exemple :-

item1
item2
item3 item4 item 5
item6

Comment est-il possible de faire cela?

(Si vous vous demandez pourquoi j'aurais jamais besoin d'une telle chose, un exemple de scénario serait des "mises à jour de style Facebook" où si un utilisateur télécharge 3-4 photos en continu, ils n'apparaissent pas toujours sur la ligne suivante, mais cela peut apparaître horizontalement alors que S'il publie un événement, il apparaît dans la ligne suivante.)

Merci d'avance :)

Était-ce utile?

La solution

Les fonds de la solution consiste à utiliser un autre ItemsControl dans le ItemTemplate de la ListBox. Cette ItemsControl devrait avoir un orienté horizontal StackPanel comme ItemsPanel.

Voici un exemple de base. Commençons par des testdata très simples: -

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

    }
}

Maintenant, nous voulons afficher cette liste dans une boîte de liste, mais gardez tous les noms qui ont la même première initiale sur la même ligne. Je vais utiliser une implémentation de IValueConverter Pour faire face au groupe dont nous avons besoin. Si vous utilisez MVVM, vous auriez votre vue ViewModel.

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

La sortie de ce convertisseur est essentiellement IEnumerable<IEnumerable<string>> C'est ce que nous voulons. La boîte à liste extérieure énumera l'ensemble extérieur et l'intérieur ItemsControl Énumera l'ensemble intérieur de chaînes qui sera un ensemble de noms avec la même initiale.

Voici le 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>

Autres conseils

Si vous utilisez le Modèle MVVM Je ferais quelque chose comme ça:

  1. Créez un ViewModel pour la vue dans votre liste de liste. Cette machine virtuelle contient une collection de ListItemViewModel instances (voir point suivant)
  2. Créez un ViewModel appelé listItemViewModel (donnez-lui un nom plus approprié, en fonction de votre domaine). Ce modèle de vue contient une collection d'instances ItemViewModel (voir point suivant).
  3. Créez un ViewModel appelé itemViewModel. Chacun d'eux soutient un seul élément de la liste. Donnez-le un nom plus approprié en fonction de votre domaine.
  4. Créez une vue qui contient votre boîte de liste. Bonnez-vous votre ListBox à la collection de ListItemViewModels dans la machine virtuelle. Le modèle d'élément pour cette zone de liste sera un listItemView (voir point suivant). Le modèle de panneau d'éléments sera le StackPanel par défaut.
  5. Créez un ListItemView qui possède un contexte de données ListItemViewModel. Cette vue se compose d'un stackpanel horizontal de ViewViews (voir point suivant).
  6. Créez un élémentView qui est soutenu par l'élémentViewModel.

Votre point de vue ressemblerait à ceci, chacun avec un ViewModel correspondant.

Comme je l'ai dit ci-dessus, vous voudrez certainement changer le nom de vos modèles de vues / vue, les miens sont à des fins de démonstration uniquement :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top