6

首先,是上一篇文章,它处理从类中绑定到我的 Accounts的ListBoxAccountListBox 数据。ObservableCollection<Account>AccountsCollection.cs

所以现在我有一个绑定对象 AccountsCollection 和一个名为 AccountTemplate 的 DataTemplate,用于在资源中定义的 ListBox:

<Window.Resources>
    <controller:AccountsWindowController x:Key="AccountsCollection" />
    <DataTemplate x:Key="AccountTemplate">
        <DockPanel>
            <Button Name="EditButton" 
                    DockPanel.Dock="Right" 
                    Margin="3 0 3 0" 
                    VerticalAlignment="Center" 
                    Content="Edit" />
            <Button Name="DeleteButton" 
                    DockPanel.Dock="Right" 
                    Margin="3 0 3 0" 
                    VerticalAlignment="Center" 
                    Content="Delete" />
            <TextBlock Name="AccountName" 
                       VerticalAlignment="Center" 
                       Text="{Binding Name}" 
                       TextWrapping="NoWrap"
                       TextTrimming="CharacterEllipsis" />
        </DockPanel>
    </DataTemplate>
<Window.Resources>

这是与 LisBox 本身相关的代码:

<ListBox Name="AccountsListBox" 
         Margin="12,38,12,41" 
         HorizontalContentAlignment="Stretch" 
         ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
         ItemsSource="{Binding Accounts, 
             Source={StaticResource ResourceKey=AccountsCollection}}" 
         ItemTemplate="{StaticResource ResourceKey=AccountTemplate}" 
         MouseDoubleClick="AccountsListBox_MouseDoubleClick">
</ListBox>

我希望我的列表设计为通过起始字母对所有帐户进行分组,并在列表中显示该字母(另外我想对该字母标题应用一些设计)。最终结果应该是这样的:

替代文字

感谢所有的帮助!

更新:这是成功实现分组的代码。

<Window x:Class="Gui.Wpf.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:entities="clr-namespace:Entities.Accounts;assembly=Entities" 
    xmlns:contollers="clr-namespace:Gui.Wpf.Controllers" 
    xmlns:converters="clr-namespace:Gui.Wpf.Converters" 
    xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" 
    Title="MainWindow" 
    Width="525" 
    Height="350" >

<Window.Resources>

    <!-- Main window controller -->
    <contollers:MainWindowController 
        x:Key="MainWindowController" />

    <!-- Converter for first letter extraction from the account name -->
    <converters:FirstLetterConverter x:Key="FirstLetterConv" />

    <!-- View source for the AccountsListBox -->
    <CollectionViewSource 
        x:Key="AccountsView" 
        Source="{Binding Accounts, Source={StaticResource ResourceKey=MainWindowController}}">

        <!-- Sorting -->
        <CollectionViewSource.SortDescriptions>
            <componentModel:SortDescription PropertyName="AccountName" />
        </CollectionViewSource.SortDescriptions>

        <!-- Grouping -->
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="AccountName" Converter="{StaticResource ResourceKey=FirstLetterConv}" />
        </CollectionViewSource.GroupDescriptions>

    </CollectionViewSource>

    <!-- Data template for the type Account -->
    <DataTemplate 
        DataType="{x:Type entities:Account}">
        <DockPanel>
            <Button 
                Name="DeleteButton" 
                DockPanel.Dock="Right" 
                Margin="3, 1, 3, 1" 
                VerticalAlignment="Center" 
                Content="Delete" />
            <Button 
                Name="EditButton" 
                DockPanel.Dock="Right" 
                Margin="3, 1, 3, 1" 
                VerticalAlignment="Center" 
                Content="Edit" />
            <TextBlock 
                Name="AccountNameTextBlock" 
                VerticalAlignment="Center" 
                Text="{Binding AccountName}" 
                TextWrapping="NoWrap" 
                TextTrimming="CharacterEllipsis" />
        </DockPanel>

    </DataTemplate>

    <!-- Data template for AccountListBox grouping -->
    <DataTemplate x:Key="GroupingHeader">
        <TextBlock Text="{Binding Path=Name}" Background="Black" Foreground="White" />
    </DataTemplate>

</Window.Resources>

<Grid>
    <ListBox 
        Name="AccountsListBox" 
        Width="300" 
        Height="200" 
        HorizontalAlignment="Center" 
        VerticalAlignment="Center" 
        ItemsSource="{Binding Source={StaticResource ResourceKey=AccountsView}}" 
        HorizontalContentAlignment="Stretch" >
        <ListBox.GroupStyle>
            <GroupStyle 
                HeaderTemplate="{StaticResource ResourceKey=GroupingHeader}" />
        </ListBox.GroupStyle>
    </ListBox>
</Grid>

4

2 回答 2

15

您可以使用CollectionViewSource, 和转换器来提取第一个字母:

<local:FirstLetterConverter x:Key="firstLetterConverter" />

<CollectionViewSource x:Key="cvs" Source="{Binding Accounts, Source={StaticResource AccountsCollection}}">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="AccountName" />
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="AccountName" Converter="{StaticResource firstLetterConverter}" />
    </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

...

<ItemsControl ItemsSource="{Binding Source={StaticResource cvs}}">
    ...

转换器:

public class FirstLetterConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string s = value as string;
        if (s != null && s.Length > 0)
            return s.Substring(0, 1);
        return string.Empty;
    }

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

如果要将样式应用于组,可以使用该GroupStyle属性:

  ...
  <ItemsControl.GroupStyle>
    <GroupStyle>
      <GroupStyle.HeaderTemplate>
        <DataTemplate>
          <TextBlock FontWeight="Bold" FontSize="15" Text="{Binding Path=Name}" />
        </DataTemplate>
      </GroupStyle.HeaderTemplate>
      <GroupStyle.ContainerStyle>
        <Style TargetType="{x:Type GroupItem}">
          <Setter Property="Background" Value="Gray" />
          <Setter Property="Foreground" Value="White" />
        </Style>
      </GroupStyle.ContainerStyle>
    </GroupStyle>
  </ItemsControl.GroupStyle>
  ...
于 2010-11-24T13:24:00.880 回答
2

这是一个非常相似的解决方案示例:

首先,我们需要为您生成更好的集合DataContext- 这是一个您可以轻松修改以用于您的目的的示例 -

public Window1()
{
    InitializeComponent();
    var s = new[] { "Dave", "Adam", "Jeny", "Nick", "James" };
    DataContext = s
        .Select(n => n[0])
        .Distinct()
        .ToDictionary(l => l.ToString(), l => s
            .Where(w => w
                .StartsWith(l.ToString())));
}

那么我们只需要 UI 的嵌套 ItemsControls -

<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
  <DataTemplate>
    <StackPanel>
      <TextBlock Foreground="Red" Text="{Binding Key}" FontSize="12" Margin="5" />
      <ItemsControl ItemsSource="{Binding Value}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="5">
              <Button Content ="View" Margin="0,0,5,0" />
              <Button Content ="Delete"  Margin="0,0,5,0" />
              <TextBlock Text="{Binding}" />
            </StackPanel>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
      </ItemsControl>
    </StackPanel>
  </DataTemplate>
</ItemsControl.ItemTemplate>

我们得到了这个:

替代文字

于 2010-11-24T12:17:50.643 回答