13

多くのキー数値を持つプロジェクトを含む WPF DataGrid を実装しています。プロジェクトは、プロジェクト カテゴリ別にグループ化されます。

各カテゴリには、次のものが必要です。

  1. 列のすべての行の合計を各キー数値列に表示する行。
  2. バインドされたデータソース グリッドの一部ではないターゲット行。目標行は、すべての列について、その年の目標を示します (例: 支出する金額)。

これらの行は、各グループで常に一番上にある必要があります (ソート フィルタリング)。

私の最初の解決策は、このデータをグループ ヘッダーに含めることでした。グループ ヘッダーは列をサポートしていないため、これは適切なソリューションではありません。つまり、列幅を取得して構築する必要があります。

それは可能ですが、ユーザーが列を並べ替えて非表示にしたい場合は複雑になります。

DataGrid は CollectionViewSource を使用しているため、C# コードが入力されていません。基本的に私はこの例を拡張しています: http://msdn.microsoft.com/en-us/library/ff407126.aspx

よろしくお願いいたします - マティ

4

2 に答える 2

2

プロジェクトの1つにグループ小計行を持つハッキングされたDataGridがあります。列の非表示や並べ替えなど、あなたが提起する問題のいくつかについては心配していなかったので、それを拡張できるかどうかはわかりません。また、大きなセットで問題になる可能性のあるパフォーマンスの問題がある可能性があることも認識しています(私のウィンドウは32個の個別のDataGridを操作しています-痛いです)。しかし、それは私が見た他の解決策とは異なる方向なので、私はそれをここに投げて、それがあなたを助けるかどうか見ると思いました。

私のソリューションは、2つの主要なコンポーネントで構成されて
います。1。小計行は、メインのDataGridの行ではなく、個別のDataGridです。実際には、各グループに2つの追加グリッドがあります。1つはグループが折りたたまれているときにのみ表示されるヘッダーにあり、もう1つはItemsPresenterの下にあります。小計DataGridsのItemsSourceは、グループ内のアイテムを取得し、集約ビューモデルを返すコンバーターから取得されます。小計グリッドの列は、メイングリッドとまったく同じです(DataGrid_Loadedに入力されていますが、xamlでも実行できると確信しています)。

            <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.次に、問題は、すべてのDataGridを単一のグリッドであるかのように動作させる方法です。これは、GridクラスのSharedSizeGroupの動作を模倣するというクラスでサブクラス化することで処理しましたDataGridTextColumn(この場合はテキストのみですが、他の列タイプも機能するはずです) 。DataGridSharedSizeTextColumnグループ名を持つ文字列依存関係プロパティがあり、同じグループ内のすべての列を追跡します。1つの列で変更があった場合Width.DesiredValue、他のすべての列のMinWidthを更新し、を使用して強制的に更新しDataGridOwner.UpdateLayout()ます。このクラスは列の並べ替えもカバーしており、DisplayIndexが変更されるたびにグループ全体の更新を行います。このメソッドは、セッターがあれば、他の列プロパティでも機能すると思います。

選択やコピーなどで解決するのは他にも厄介なことがありました。しかし、MouseEnteredイベントとMouseLeaveイベントを使用したり、カスタムのコピーコマンドを使用したりすると、非常に簡単に処理できることがわかりました。

于 2012-06-01T14:40:30.953 に答える
0

1 つのオプションとして、意味をなさない名前やその他のフィールドの特別な値を持つ行をデータ ソースに追加し、DataTrigger を使用してそれらを特別な色やその他の色で表示することができます。

いずれにしてもフィルタリングは C# で行われるため、これらの行には影響しません。

ここでの唯一の問題は並べ替えです。一部の行は常に順序 0 であり、グループ内の順序は 1 であると言うだけでもとてもクールです。しかし、それを行う方法がわからないので、並べ替えを宣言するだけでなく、すべての列に対して C# でカスタム並べ替えを行う必要があります。

<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:他のすべてに加えて、最初のソリューション(グループヘッダーの合計情報)と比較して大きな欠点があります。これは、変更をフィルタリングするときに、表示されている行に対してのみ計算されるように合計を更新する必要があるためです。

したがって、この答えは完全なハックであり、すべての優雅さが欠けており、WPFが持つと思われる優れた機能を使用していません:(

于 2012-05-20T17:44:03.643 に答える