自定义WPF DataGrid中的行组

时间:2016-06-02 15:18:07

标签: wpf xaml datagrid

我想创建一个与此example

类似的DataGrid

现在我创建了一个看起来像

的DataGrid

DataGrid

这是我的代码:

<DataGrid
    ScrollViewer.IsDeferredScrollingEnabled="True"
    Grid.Row="1"
    AutoGenerateColumns="False"
    CanUserAddRows="False"
    CanUserDeleteRows="False"
    CanUserSortColumns="True"
    EnableColumnVirtualization="True"
    EnableRowVirtualization="True"
    ItemsSource="{Binding MusicManager.MusicDataManager.Albums.Albums}"
    VirtualizingPanel.ScrollUnit="Pixel"
    VirtualizingStackPanel.VirtualizationMode="Recycling">
    <DataGrid.Columns>
        <DataGridTemplateColumn
            Width="auto"
            MaxWidth="150"
            Header="Duration">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="auto" />
                            <RowDefinition Height="auto" />
                            <RowDefinition Height="auto" />
                            <RowDefinition Height="auto" />
                        </Grid.RowDefinitions>

                        <myControls:ImageProviderViewer
                            Grid.Row="0"
                            Width="90"
                            Height="90"
                            Margin="0"
                            HidePlaceholderAtBeginning="True"
                            HighPriorityImage="True">
                            <myControls:ImageProviderViewer.ImageProvider>
                                <MultiBinding Converter="{StaticResource AlbumCoverConverter}">
                                    <Binding Path="DataContext" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" />
                                    <Binding Path="Guid" />
                                </MultiBinding>
                            </myControls:ImageProviderViewer.ImageProvider>
                            <myControls:ImageProviderViewer.Placeholder>
                                <Viewbox Width="85" Height="85">
                                    <Path Fill="Gray" Data="{StaticResource VectorMicrophone}" />
                                </Viewbox>
                            </myControls:ImageProviderViewer.Placeholder>
                        </myControls:ImageProviderViewer>


                        <TextBlock
                            Grid.Row="1"
                            Grid.ColumnSpan="2"
                            Width="auto"
                            Margin="2"
                            FontSize="12"
                            Text="{Binding Name}"
                            TextWrapping="Wrap" />
                        <TextBlock
                            Grid.Row="2"
                            Grid.ColumnSpan="2"
                            Width="auto"
                            Margin="2"
                            FontSize="12"
                            Text="{Binding Artists, Converter={StaticResource AlbumArtistConverter}}"
                            TextWrapping="Wrap" />
                        <TextBlock
                            Grid.Row="3"
                            Grid.ColumnSpan="2"
                            Width="auto"
                            Margin="2"
                            FontSize="12"
                            TextWrapping="Wrap">
                            <TextBlock.Text>
                                <MultiBinding Converter="{StaticResource AlbumTracksConverter}" StringFormat="Tracks:   {0:F2}">
                                    <Binding Path="DataContext" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" />
                                    <Binding Path="Guid" />
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTemplateColumn Width="*">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <DataGrid
                        AutoGenerateColumns="False"
                        CanUserAddRows="False"
                        CanUserDeleteRows="False"
                        CanUserSortColumns="True"
                        EnableColumnVirtualization="True"
                        EnableRowVirtualization="True">
                        <i:Interaction.Behaviors>
                            <services:IgnoreMouseWheelBehavior />
                        </i:Interaction.Behaviors>
                        <DataGrid.ItemsSource>
                            <MultiBinding Converter="{StaticResource AlbumTracksCollectionConverter}">
                                <Binding Path="DataContext" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" />
                                <Binding Path="Guid" />
                            </MultiBinding>
                        </DataGrid.ItemsSource>
                        <DataGrid.Columns>
                            <DataGridTemplateColumn
                                Width="*"
                                MaxWidth="500"
                                Header="Title">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>


                            <DataGridTemplateColumn
                                Width="*"
                                MaxWidth="500"
                                Header="Album">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Album.Name}" TextWrapping="Wrap" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>

                            <DataGridTemplateColumn
                                Width="auto"
                                MaxWidth="500"
                                Header="Duration">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Duration}" TextWrapping="Wrap" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>

                            <DataGridTemplateColumn
                                Width="auto"
                                MaxWidth="500"
                                Header="Year">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Year}" TextWrapping="Wrap" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

    </DataGrid.Columns>
</DataGrid>

但这不是我需要的。 DataGrid在滚动时非常慢。 另外,我需要一次调整所有列的大小。

这个问题有解决方法吗?

1 个答案:

答案 0 :(得分:2)

您可以使用DataGrid的内置分组功能。我将展示一个具有所需布局的简化示例,但它需要自定义Expanders,DataGridColumnHeader,Images等。

我的简化项目类:

public class AlbumVm
{
    public string Name { get; set; }
    public Brush Color { get; set; }
}

public class SongVm
{
    public string Title { get; set; }
    public string Duration { get; set; }

    public AlbumVm Album { get; set; }
}

我使用Name="Music"分配给DataGrid的ItemsSource(125张专辑,每张5首歌曲)

var colors = new[] { Brushes.Crimson, Brushes.LimeGreen, Brushes.Cyan };
var albums = Enumerable.Range(1, 125)
             .Select(i => new AlbumVm {Name = "A" + i, Color = colors[i%colors.Length]});

var songs = albums.SelectMany(a => Enumerable.Range(1, 5)
                                   .Select(i => new SongVm {Title = a.Name + "." + i, Album = a, Duration = i + ":00"}))
                    .ToList();

var songsView = new ListCollectionView(songs);
songsView.GroupDescriptions.Add(new PropertyGroupDescription("Album.Name"));

Music.ItemsSource = songsView;

ListCollectionView支持开箱即用分组。

这里是带有自定义GroupStyle的dataGrid( VirtualizingPanel.IsVirtualizingWhenGrouping 属性需要 .Net 4.5 !)

<DataGrid Name="Music" 
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            AutoGenerateColumns="False" 
            EnableColumnVirtualization="True"
            EnableRowVirtualization="True"
            VirtualizingStackPanel.IsVirtualizing="True"
            VirtualizingPanel.IsVirtualizingWhenGrouping="True"
            VirtualizingStackPanel.VirtualizationMode="Recycling"
            ColumnWidth="*">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"/>
        <DataGridTextColumn Header="Album" Binding="{Binding Path=Album.Name}"/>
        <DataGridTextColumn Header="Duration" Binding="{Binding Path=Duration}"/>
    </DataGrid.Columns>
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>

                                    <!--Image placeholder-->
                                    <Border Margin="5" Width="100" 
                                            Background="{Binding Path=Items[0].Album.Color}"/>

                                    <Expander Grid.Column="1" IsExpanded="True">
                                        <Expander.Header>
                                            <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="{Binding Path=Name}" Margin="5"/>
                                                <TextBlock Text="{Binding Path=ItemCount}" Margin="5"/>
                                            </StackPanel>
                                        </Expander.Header>
                                        <ItemsPresenter />
                                    </Expander>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
</DataGrid>

preview

相关帖子:

WPF DataGrid Grouping with sums and other fields

WPF DataGrid Virtualization with Grouping