C# - すぐに使える WPF DataGrid を使用して前処理された動的データを表示する

okwaves2024-01-25  11

編集 2;リンクされた StackOverflow の質問で受け入れられた回答は、実際には私には機能しません。コンパイルされて問題なく見えますが、質問の図のようにデータが視覚化されません(これも私にとっては)。グループ化された実際のアイテム ソースの行ではなく、グループ化オブジェクトを含む行のフラット リストが表示されます。 答えはDataGridについては明示的に言及していませんが、ListViewについては言及しています。どちらのコントロールもコレクションごとに同じ CollectionView オブジェクトを使用するため、ListView で機能するものは DataGrid でも機能します。 また、WPF コントロールでバインドがどのように行われるかについても示されていません。このアプローチは、ある時点では機能していましたが、現在は機能しなくなっているか、これまで機能していないかのどちらかです。 私の質問とリンクされた質問はどちらも、DynamicData を使用して通常 Lis を使用するフィルタリングを行うことに関するものです。すぐに使える WPF の tCollectionView。項目をフラット化し、デフォルトの ListCollectionView を使用してグループ化、並べ替え、フィルター処理を実行すると、パフォーマンスや使いやすさの理由を問わず、その目的が果たせなくなります。 この質問が XY 問題になったのは、WPF コントロールが ICollectionView のみを理解し、DynamicData データがあり、両方をブリッジするアダプターが論理的に聞こえるという私の推論のためかもしれません。

編集 1;はっきり言っておきます。私は、グループ化されたオブジェクトの変更セットを作成することになる状況について話しています。たとえば、IObservable<IChangeSet<T>>ここで、T はItemGroup: System.Linq.IGrouping です。 問題は、項目のソースがすでに事前にグループ化されている (階層化されている) ことをデータ グリッド コントロールに適切に伝えることにあります。 事前ソートについて言及していることに気づきました編集および事前フィルタリングすると、要点を逸脱して混乱が生じた可能性があります。

WPF Datagrid コントロールを介して DynamicData から取得される、事前に並べ替え、フィルター処理、およびグループ化されたデータを視覚化する方法のデモを探しています。 私の目的は、ItemsSource が ListCollectionView であるかのように XAML コードを作成することです。データは、監視可能なコレクションにバインドされた動的データ変更セット演算子によって生成されます。

私が見つけることができた 2 つのスニペットは、「すぐに使える」組み合わせの可能性をほのめかしています。 DynamicData を使用した WPF データ グリッド;

https://stackoverflow.com/a/52928955 https://github.com/RolandPheasant/DynamicData.Snippets/blob/master/DynamicData.Snippets/Group/XamarinFormsGrouping.cs

どちらも正しいインターフェイスの実装に関係しているため、コードを次のように接着します。WPF では残りを処理できます。提案をテストしましたが、機能させることができませんでした。グリッドには、最も外側のオブジェクトのプロパティ (ItemGroup.Key や ItemsGroup.Count など) が表示されているだけです。私の期待は、グループ スタイル テンプレートによってグループ コンテナーが定義されているグループ化されたオブジェクトのレコードをグリッドに表示することです。グリッドは、単に項目ソースが項目のフラットなリスト (実際には事前にグループ化されている) であるかのように動作します。 これまでのところ、参照ソースは実際にはサポートされていないことを理解しました。

2 番目の試みは、DynamicData 結果とデータ グリッド コントロールの間でプロキシを行うカスタム CollectionView を実装することによって行われました。せいぜい視覚的な不具合が生じる程度です。それもうまくいきませんでした。

明白な問題に気づくほど賢くないか、WPF コントロールとの統合が難しいかのどちらかですd. この問題の解決方法を教えていただくか、希望どおりに動作するコードを教えてください。

必要に応じて、独自のグルー コードや拡張機能を作成することを躊躇しません。おそらく WPF はこの種のリクエストには適していない可能性があり、その場合は代替案を歓迎します。 このトピックまで、私は自分自身をかなり熟練したプログラマーだと思っていましたが、この障害が私に精神的な打撃を与えました。

DynamicData は、SourceList からのバインディングをサポートします。または SourceCache<T>表示目的で通常のコレクションに直接コピーします。 mySourceList.Conn を呼び出すだけです。ect().Bind(myObservableCollection).Subscribe(); SourceList<T> に変更を加えます。オブジェクトは自動的に ObservableCollection<T> にマッピングされます。

– ブランドン・クレイマー

2020 年 9 月 3 日 17:41

@BrandonKramer あなたのコメントを見て、私は要点を理解できていないことに気づきました。いくつかの説明を追加しました。

– バート

2020 年 9 月 3 日 18:42

あなたが今何に苦労しているかわかります。問題は、基本的に、単一のグリッドをリストのリストから変更セットにバインドしようとしているということです。この場合の解決策は、グループを 1 つのリストにフラット化し、グリッド自体で視覚的なグループ化を実行することです。それか、ネストされたグリッド (各行が別のグリッドであるグリッドなど) を使用してみることもできますが、作成するのは非常に面倒で、多くの作業を行わないと見栄えが良くない可能性があります。

– ブランドン・クレイマー

2020 年 9 月 3 日 18:57

WPF には ICollectionView と ICollectionViewLiveShaping があり、(複数) グループ化され、フィルター処理され、並べ替えられたビューが ItemsSource オブジェクトにすでに表示されています。 ICollectionView と DynamicData の間のアダプターが機能するかどうか、またどのように機能するか、または目的の目標を達成するための別の方法を誰かが教えてくれることを願っています。

– バート

2020 年 9 月 3 日 19:42

CollectionView は、コレクションにバインドするたびに暗黙的に使用されます。通常、自分で作成したり作業したりする必要があるものではありません。あなたがしなければならないことは、IEnumerable<IChangeSet&lを変換することですt;アイテムグループ>> WPF がバインド方法を認識しているフォームに変換します。これを行う最も簡単な方法は、Select().Merge() を介してコレクションをフラット化することです。ビューモデル内のデータを変換したくない場合は、前述のようにビューで WPF データ テンプレートを使用して、各行を独自のグリッド、リストビュー、またはその他のコレクション表示オブジェクトにします。

– ブランドン・クレイマー

2020 年 9 月 3 日 19:52



------------------------

WPF DataGrid で事前にグループ化されたデータ (例: IEnumerable) を表示する最も簡単な方法は次のとおりです。データ テンプレートを使用して、ネストされた DataGrid にグループのコンテンツを表示します。

例:

<Window x:Class="GroupingDisplay.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:GroupingDisplay"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid ItemsSource="{Binding GroupingData}" HeadersVisibility="None" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Key, Mode=OneWay}"/>
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <StackPanel>
                        <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
                            <DataGrid.Columns>
                                <DataGridTextColumn Binding="{Binding Data, Mode=OneWay}"/>
                            </DataGrid.Columns>
                        </DataGrid>
                    </StackPanel>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

背後のコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace GroupingDisplay
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public List<IGrouping<int, TestClass>> GroupingData { get; }
        public MainWindow()
        {
            InitializeComponent();

            var testData = new TestClass[]
            {
                new TestClass(1, "Horse"),
                new TestClass(1, "Cow"),
                new TestClass(2, "Bike"),
                new TestClass(2, "Car"),
                new TestClass(3, "House"),
                new TestClass(3, "Hotel")
            };

            GroupingData = testData
                .GroupBy(x => x.Key)
                .ToList();

            DataContext = this;
        }
    }

    public class TestClass
    {
        public int Key { get; }
        public string Data { get; }

        public TestClass(int key, string data)
        {
            Key = key;
            Data = data;
        }
    }
}

上記の単純なクラスでは、各グループ (1、2、および 3) に 1 つずつ、合計 3 つの行が表示されます。 次に、行をクリックすると展開され、そのグループの内容が表示されます。

すべてのグループのコンテンツを自動的に表示したい場合は、親 DataGrid の RowDetailsVisibilityMode="Visible" を設定できます。

1

完了事項を記入するために時間を割いていただきありがとうございますコントロールのネストに関する例。その間に、すでにグループ化されたデータをラップするカスタム listcollectionview を構築しようとしましたが、それは機能しました。私はここで PoC を構築しました: github.com/Bert-Proesmans/dynamic-data-collectionview。残っているのは、必要なオブジェクトを生成するための直感的な API を一般化して構築することだけです。

– バート

2020 年 9 月 14 日 7:59

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。