comment gérer le total partiel du groupe et, par exemple, les rangées cibles dans la DataGrid WPF?

je suis en train de mettre en place un DataGrid WPF qui contient des projets avec de nombreux chiffres clés. Les projets sont regroupés par catégories de projets.

Pour chaque catégorie, il devrait être:

  1. une ligne qui montre dans chaque colonne de chiffre clé la somme de toutes les lignes de la colonne.
  2. une ligne cible qui ne fait pas partie de la grille source de données dans binded to. ligne cible indique pour chaque colonne, ce qui est de la cible pour l'année (par exemple, combien d'argent il y a à passer.)

ces lignes doivent toujours être en haut dans chaque groupe (tri filtrage).

Ma 1ère solution était d'avoir ces données en-tête de groupe. Ce n'est pas une bonne solution parce que l'en-tête de groupe ne supporte pas les colonnes. i.e. il devrait être construit en obtenant des largeurs de colonne.

cela pourrait être fait mais cela devient compliqué quand les utilisateurs veulent réorganiser et cacher des colonnes.

DataGrid utilise CollectionViewSource donc il n'est pas rempli avec C# code. En gros, je vais étendre cet exemple:http://msdn.microsoft.com/en-us/library/ff407126.aspx

Merci Et Meilleures Salutations - matti

12
demandé sur char m 2012-05-18 15:55:17

2 réponses

j'ai un DataGrid hacké avec des lignes de sous-total de groupe dans un de mes projets. Nous n'étions pas préoccupés par certaines des questions que vous soulevez, comme la dissimulation et le tri des colonnes, donc je ne sais pas si elle peut être prolongée pour cela. Je réalise également qu'il pourrait y avoir des problèmes de performance qui pourraient être un problème avec les grands ensembles (ma fenêtre fonctionne 32 DataGrids séparés - ouch). Mais c'est une direction différente des autres solutions que j'ai vu, alors j'ai pensé le jeter ici et voir si elle vous aide.

ma solution se compose de 2 Composants principaux:

1. Les lignes de sous-total ne sont pas des lignes dans le DataGrid principal, mais sont des DataGrids séparés. J'ai 2 grilles dans chaque groupe: 1 dans l'en-tête est affiché uniquement lorsque le groupe est réduit, et un sous le ItemsPresenter. La source des éléments pour les DataGrids de sous-total provient d'un convertisseur qui prend les éléments dans le groupe et retourne un modèle de vue agrégée. Les colonnes des grilles de sous-total sont exactement le même que la grille principale (rempli dans DataGrid_Loaded, mais je suis sûr que cela pourrait être fait dans xaml aussi).

            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Expander Background="Gray" HorizontalAlignment="Left" IsExpanded="True"
                                              ScrollViewer.CanContentScroll="True">
                                        <Expander.Header>
                                            <DataGrid Name="HeaderGrid" ItemsSource="{Binding Path=., Converter={StaticResource SumConverter}}"
                                                        Loaded="DataGrid_Loaded" HeadersVisibility="Row"
                                                        Margin="25 0 0 0" PreviewMouseDown="HeaderGrid_PreviewMouseDown">
                                                <DataGrid.Style>
                                                    <Style TargetType="DataGrid">
                                                        <Style.Triggers>
                                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=IsExpanded}"
                                                                            Value="True">
                                                                <Setter Property="Visibility" Value="Collapsed"/>
                                                            </DataTrigger>
                                                        </Style.Triggers>
                                                    </Style>
                                                </DataGrid.Style>
                                            </DataGrid>
                                        </Expander.Header>
                                        <StackPanel>
                                            <ItemsPresenter/>
                                            <DataGrid Name="FooterGrid" ItemsSource="{Binding ElementName=HeaderGrid, Path=ItemsSource, Mode=OneWay}"
                                                            Loaded="DataGrid_Loaded" HeadersVisibility="Row"
                                                            Margin="50 0 0 0">
                                                <DataGrid.Style>
                                                    <Style TargetType="DataGrid">
                                                        <Style.Triggers>
                                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=IsExpanded}"
                                                                         Value="False">
                                                                <Setter Property="Visibility" Value="Collapsed"/>
                                                            </DataTrigger>
                                                        </Style.Triggers>
                                                    </Style>
                                            </DataGrid>
                                        </StackPanel>
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>



2. Ensuite, la question Est de savoir comment toutes les DataGrids doivent se comporter comme s'ils étaient une seule grille. J'ai manipulé que par des sous-classement DataGridTextColumn (nous n'avons que du texte dans ce cas, mais les autres types de colonnes devraient fonctionner aussi) dans une classe appelée DataGridSharedSizeTextColumn qui imite le comportement du SharedSizeGroup de la classe de grille. Il a une propriété de dépendance string avec un groupe nom et conserve la trace de toutes les colonnes dans le même groupe. Lorsque Width.DesiredValue les changements dans une colonne, je vais mettre à jour le MinWidth dans toutes les autres colonnes et de forcer une mise à jour avec DataGridOwner.UpdateLayout(). Cette classe couvre également la réorganisation des colonnes et fait une mise à jour à l'échelle du groupe chaque fois que DisplayIndex change. Je pense que cette méthode fonctionnerait aussi avec n'importe quelle autre propriété de colonne aussi longtemps qu'elle a un setter.

il y avait d'autres choses agaçantes à régler avec la sélection, la copie, etc. Mais il s'est avéré être assez facile à gérer avec les événements MouseEntered et MouseLeave et en utilisant une commande de copie personnalisée.

2
répondu tordal 2012-06-01 14:40:30

une option pourrait être d'ajouter les lignes dans la source de données avec des valeurs spéciales pour le nom et d'autres champs qui n'ont pas de sens et utiliser DataTrigger pour les montrer avec des couleurs spéciales et peut-être d'autres.

Le filtrage est fait en C# de toute façon donc il n'affecte pas ces lignes.

Tri est le seul problème ici. Ce serait tellement cool juste pour dire que certaines lignes sont toujours à l'ordre 0 et d'ordre 1 dans le groupe. Mais parce que je ne sais pas comment le faire je dois faire sur mesure le tri en C# pour toutes les colonnes au lieu de simplement déclarer le tri:

<CollectionViewSource.SortDescriptions>
   <!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
    <scm:SortDescription PropertyName="ProjectName"/>
    <scm:SortDescription PropertyName="Complete" />
    <scm:SortDescription PropertyName="DueDate" />
</CollectionViewSource.SortDescriptions>

EDIT: en plus de tout le reste il a un inconvénient majeur par rapport à ma 1ère solution (sum info dans l'en-tête de groupe) parce que lors du filtrage des modifications je devrais mettre à jour les sommes à calculer uniquement pour les lignes visibles.

Donc, cette réponse est un hack et dépourvu de toute l'élégance et n'utilise pas de fonctionnalités intéressantes que WPF est supposer :(

0
répondu char m 2012-05-20 19:19:50