Regroupement par valeur de propriété à l'aide de LINQ
-
21-12-2019 - |
Question
Je voulais créer un LongListSelector
contrôle dans lequel les valeurs sont regroupées en plusieurs catégories.Chaque élément a ces propriétés :
Public Class SideItem
Private _Title As String
Public Property Title As String
Get
Return _Title
End Get
Set(value As String)
_Title = value
End Set
End Property
Private _Icon As System.Windows.Shapes.Path
Public Property Icon As System.Windows.Shapes.Path
Get
Return _Icon
End Get
Set(value As System.Windows.Shapes.Path)
_Icon = value
End Set
End Property
Private _Category As String
Public Property Category As String
Get
Return _Category
End Get
Set(value As String)
_Category = value
End Set
End Property
Private _NavigationUri As Uri
Public Property NavigationUri As Uri
Get
Return _NavigationUri
End Get
Set(value As Uri)
_NavigationUri = value
End Set
End Property
End Class
J'aimerais regrouper une liste de SideItem
en fonction de la valeur de Category
propriété.J'ai regardé plusieurs exemples mais je n'ai pas réussi à le faire.C'est ma dernière tentative (parmi plusieurs)
Me.Items = (From data In L
Group data By Key = New With {Key data.Category} Into Group
Select New SideItem With {
.Category = Key.Category, _
.Title = Group.Select(Function(itm As SideItem) itm.Title), _
.Icon = Group.Select(Function(itm As SideItem) itm.Icon), _
.NavigationUri = Group.Select(Function(itm As SideItem) itm.NavigationUri)
}).OfType(Of SideItem)()
MISE À JOUR:SOLUTION
J'ai utilisé le code que vous pouvez trouver dans la réponse de Verdesrobert, voté comme le meilleur, mais j'ai édité le AlphaKeyGroup
cours afin de répondre à mes besoins.
Public Class AlphaKeyGroup(Of T)
Inherits List(Of T)
Public Delegate Function GetKeyDelegate(item As T) As String
Public Property Key() As String
Get
Return m_Key
End Get
Private Set(value As String)
m_Key = value
End Set
End Property
Private m_Key As String
Public Sub New(key__1 As String)
Key = key__1
End Sub
Private Shared Function CreateGroups(slg As List(Of String)) As List(Of AlphaKeyGroup(Of T))
Dim list As New List(Of AlphaKeyGroup(Of T))()
For Each key As String In slg
list.Add(New AlphaKeyGroup(Of T)(key))
Next
Return list
End Function
Public Shared Function CreateGroups(items As IEnumerable(Of T), ci As CultureInfo, getKey As GetKeyDelegate, sort As Boolean) As List(Of AlphaKeyGroup(Of T))
Dim headerList As New List(Of String)
For Each header As T In items
headerList.Add(getKey(header))
Next
Dim list As List(Of AlphaKeyGroup(Of T)) = CreateGroups(headerList)
For Each item As T In items
list(list.IndexOf(list.Where(Function(I As AlphaKeyGroup(Of T)) I.Key = getKey(item)).First)).Add(item)
Next
If sort Then
For Each group As AlphaKeyGroup(Of T) In list
group.Sort(Function(c0, c1)
Return ci.CompareInfo.Compare(getKey(c0), getKey(c1))
End Function)
Next
End If
Return list
End Function
Fin du cours
La solution
Vous avez d’abord besoin d’une classe qui fournit une structure de liste groupée :
Public Class AlphaKeyGroup(Of T)
Inherits List(Of T)
Public Delegate Function GetKeyDelegate(item As T) As String
Public Property Key() As String
Get
Return m_Key
End Get
Private Set
m_Key = Value
End Set
End Property
Private m_Key As String
Public Sub New(key__1 As String)
Key = key__1
End Sub
Private Shared Function CreateGroups(slg As SortedLocaleGrouping) As List(Of AlphaKeyGroup(Of T))
Dim list As New List(Of AlphaKeyGroup(Of T))()
For Each key As String In slg.GroupDisplayNames
list.Add(New AlphaKeyGroup(Of T)(key))
Next
Return list
End Function
Public Shared Function CreateGroups(items As IEnumerable(Of T), ci As CultureInfo, getKey As GetKeyDelegate, sort As Boolean) As List(Of AlphaKeyGroup(Of T))
Dim slg As New SortedLocaleGrouping(ci)
Dim list As List(Of AlphaKeyGroup(Of T)) = CreateGroups(slg)
For Each item As T In items
Dim index As Integer = 0
index = slg.GetGroupIndex(getKey(item))
If index >= 0 AndAlso index < list.Count Then
list(index).Add(item)
End If
Next
If sort Then
For Each group As AlphaKeyGroup(Of T) In list
group.Sort(Function(c0, c1)
Return ci.CompareInfo.Compare(getKey(c0), getKey(c1))
End Function)
Next
End If
Return list
End Function
End Class
En utilisant votre classe SideItem, vous devez ensuite créer une liste de SideItem :
// Your code to provide the list of items like this:
Dim source As New List(Of SideItem)()
//add data to the list or skip the creation and provide your data
Regroupez ensuite la liste comme ceci :
List<AlphaKeyGroup<SideItem>> DataSource = AlphaKeyGroup<SideItem>.CreateGroups(source,
System.Threading.Thread.CurrentThread.CurrentUICulture,
(SideItem s) => { return s.Category; }, true);
Lier au LongListSelector ItemsSource :
Me.ItemsSource = DataSource;
LongListSelector XAML :
<phone:LongListSelector
x:Name="Me"
JumpListStyle="{StaticResource SideItemJumpListStyle}"
Background="Transparent"
GroupHeaderTemplate="{StaticResource SideItemGroupHeaderTemplate}"
ItemTemplate="{StaticResource SideItemItemTemplate}"
LayoutMode="List"
IsGroupingEnabled="true"
HideEmptyGroups ="true"/>
Modèle d'élément XAML :
<DataTemplate x:Key="SideItemItemTemplate">
<StackPanel VerticalAlignment="Top">
<TextBlock FontWeight="Bold" Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
GroupHeaderTemplate XAML :
<DataTemplate x:Key="SideItemGroupHeaderTemplate">
<Border Background="Transparent" Padding="5">
<Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62"
Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6"
FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Border>
</Border>
</DataTemplate>
Style de liste de saut XAML :
<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
<Style x:Key="SideItemJumpListStyle" TargetType="phone:LongListSelector">
<Setter Property="GridCellSize" Value="113,113"/>
<Setter Property="LayoutMode" Value="Grid" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
<TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Cela devrait suffire.
Réponse basée sur http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj244365(v=vs.105).aspx