使用LINQ按属性值分组

时间:2014-04-13 21:09:43

标签: vb.net linq windows-phone-8 group-by longlistselector

我想创建一个LongListSelector控件,其中值被分组为多个类别。每个项目都有这些属性:

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

我想根据SideItem属性的值对Category列表进行分组。我查看了几个例子,但我没有设法做到这一点。这是我最近的尝试(有几个)

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

更新:解决方案

我在verdesrobert的答案中使用了您能找到的最佳答案,但我编辑了AlphaKeyGroup课程以满足我的需求。

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

结束班

1 个答案:

答案 0 :(得分:1)

首先,您需要一个提供分组列表结构的类:

    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

使用您的类SideItem,您应该创建一个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 

然后将列表分组如下:

List<AlphaKeyGroup<SideItem>> DataSource = AlphaKeyGroup<SideItem>.CreateGroups(source, 
            System.Threading.Thread.CurrentThread.CurrentUICulture,
            (SideItem s) => { return s.Category; }, true);

绑定到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"/>

ItemTemplate 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>

JumpListStyle 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>

这应该足够了。

根据http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj244365(v=vs.105).aspx

回答