Wie kann ich diese Art von Layout in Silverlight erhalten?
-
29-10-2019 - |
Frage
Ich habe eine Listbox und sie ist an eine Liste einfacher Objekte gebunden.Wie wir wissen, werden die Elemente der Listbox standardmäßig als Stackpanel gehostet und daher werden die Elemente auf diese Weise angeordnet
item1
item2
item3
item4
item5
item6
Allerdings habe ich einige Bedingungen, anhand derer ich überprüfe, ob der Artikel horizontal oder vertikal angezeigt werden soll und die Artikel daher auf diese Weise angeordnet werden könnten
Z.B :-
item1
item2
item3 item4 item 5
item6
Wie ist das möglich?
(Wenn Sie sich fragen, warum ich so etwas jemals brauchen sollte, wäre ein Beispielszenario „Facebook-Style-Updates“, bei dem ein Benutzer, wenn er 3-4 Fotos kontinuierlich hochlädt, nicht immer in der nächsten Zeile erscheint, sondern möglicherweise horizontal Wenn er ein Ereignis postet, erscheint es in der nächsten Zeile.)
Dank im Voraus :)
Lösung
Die Grundlage der Lösung besteht darin, einen anderen ItemsControl
im ItemTemplate
des ListBox
s zu verwenden.Dieser ItemsControl
sollte einen horizontal ausgerichteten StackPanel
als ItemsPanel
haben.
Hier ist ein grundlegendes Beispiel.Beginnen wir mit einigen sehr einfachen Testdaten: -
public class TestStringList : List<string>
{
public TestStringList()
{
AddRange(new[] {"Anthony", "Kar", "Martin", "Jon", "Erik", "Darin",
"Balus", "Mike", "Hans", "Alex", "Anomie", "David" });
}
}
Jetzt möchten wir diese Liste in einer ListBox anzeigen, aber alle Namen mit derselben ersten Initiale in derselben Zeile belassen.Ich werde eine Implementierung von IValueConverter
verwenden, um mit der Gruppierung umzugehen, die wir benötigen.Wenn Sie MVVM verwenden, muss Ihr ViewModel dies übernehmen.
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();
}
}
Die Ausgabe dieses Konverters ist im Grunde genommen IEnumerable<IEnumerable<string>>
, was wir wollen.Die äußere ListBox listet die äußere Menge auf und der innere ItemsControl
listet die innere Menge von Zeichenfolgen auf, die eine Menge von Namen mit derselben Initiale sind.
Hier ist das 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>
Andere Tipps
Bei Verwendung des MVVM-Muster Ich würde so etwas machen:
- Erstellen Sie ein ViewModel für die Ansicht, in der sich Ihr Listenfeld befindet.Diese VM enthält eine Sammlung von
ListItemViewModel
Instanzen (siehe nächster Punkt) - Erstellen Sie ein ViewModel mit dem Namen ListItemViewModel (geben Sie ihm basierend auf Ihrer Domäne einen passenderen Namen).Dieses Ansichtsmodell enthält eine Sammlung von ItemViewModel-Instanzen (siehe nächster Punkt).
- Erstellen Sie ein ViewModel mit dem Namen ItemViewModel.Jedes davon unterstützt ein einzelnes Element in der Liste.Geben Sie diesem einen passenderen Namen, basierend auf Ihrer Domain.
- Erstellen Sie eine Ansicht, die Ihre Listbox enthält.Binden Sie Ihre Listbox an die Sammlung von ListItemViewModels in der VM.Die Elementvorlage für dieses Listenfeld ist eine ListItemView (siehe nächster Punkt).Die Elementpanel-Vorlage ist das Standard-StackPanel.
- Erstellen Sie eine ListItemView mit einem ListItemViewModel-Datenkontext.Diese Ansicht besteht aus einem horizontalen StackPanel von ItemViews (siehe nächster Punkt).
- Erstellen Sie eine ItemView, die vom ItemViewModel unterstützt wird.
Ihre Ansicht würde in etwa so aussehen, jeweils mit einem entsprechenden ViewModel.
Wie ich oben sagte, möchten Sie auf jeden Fall den Namen Ihrer Ansichten/Ansichtsmodelle ändern, meine dienen nur zu Demonstrationszwecken :)