質問するログイン新規登録

Q&A

解決済

1回答

209閲覧

【WPF】DataGridにカラムが重複して表示される

Hiro987654

総合スコア1

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2025/11/25 09:36

1

0

実現したいこと

Prism, Dapperを使用して、SQLiteから取得したデータをDataGridに表示したいです。

製作中のアプリケーションはテーブル定義がインストール後に決定するため、事前にデータの構造をクラス等に定義することができません。

現在、SQLiteから取得したデータは、ObservableCollection<dynamic>型で保持しています。

発生している問題・分からないこと

SQLiteから得たデータがDataGridに表示されますが、同じカラムが2度表示されます。
SQLite側のデータが[A,B,C]と並んでいるとすると、実行した画面には[A,B,C,A,B,C]のように表示されます。

ブレークポイントを置いて表示する前のデータを確認したところ、カラムの重複はありませんでした。
DataGridにバインドした変数にマウスポインタを置くと、
{{DapperRow, A = 'TEST', B = '26', C = 'QWER'……
のように表示されます。

実行しているSQL文は、AS句でカラムに別名をつけていますが、単純なSELECT文で、テーブルの結合はしていません。

エラーメッセージ

error

1エラーメッセージはありません。 2

該当のソースコード

C#

1//SQLiteから取得したデータを保持するプロパティ 2 private ObservableCollection<dynamic> _DataRows { get; set; } 3 public ObservableCollection<dynamic> DataRows 4 { 5 get => _DataRows; 6 set 7 { 8 _DataRows = value; 9 this.RaisePropertyChanged(nameof(DataRows)); 10 } 11 }

C#

1//SQL文の実行 2 public ObservableCollection<dynamic> GetDynamicDataWithDapper(string sqlQuery) 3 { 4 using (var connection = new SqliteConnection( $"Data Source={databasePath}")) 5 { 6 var results = connection.Query<dynamic>(sqlQuery); 7 return new ObservableCollection<dynamic>(results); 8 } 9 }

C#

1//DataGridに表示する 2 public void ShowTable(string Query) 3 { 4 DataRows = GetDynamicDataWithDapper(Query); 5 }

XAML

1<!-- UIとのバインド --> 2<DataGrid Grid.Row="1" Grid.Column="0" Name="dataGrid" IsReadOnly="True" AutoGenerateColumns="True" EnableColumnVirtualization="True" ItemsSource="{Binding DataRows}" />

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

類似の事例が見つからず、参考にできませんでした。

UIとのバインドについては、Prismを使用している場合
SetProperty(ref _DataRows, value);
のように記述する例を多く見ましたが、
「CS0206 参照を返さないプロパティまたはインデクサーを out 値または ref 値として使用することはできません」
とエラーが表示されるため、
this.RaisePropertyChanged(nameof(DataRows));
のようにしています。

補足

特になし

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

guest

回答1

0

ベストアンサー

SQLiteから得たデータがDataGridに表示されますが、同じカラムが2度表示されます。
SQLite側のデータが[A,B,C]と並んでいるとすると、実行した画面には[A,B,C,A,B,C]のように表示されます。

確かにそうなりますね...
バカバカしいですが、できちゃった列を半分にするとか?w

cs

1dataGrid.AutoGeneratedColumns += (_, _) => 2{ 3 var c = dataGrid.Columns.Count; 4 for (var i = 0; i < c / 2; i++) 5 dataGrid.Columns.RemoveAt(0); // 前半を消すか後半を消すかで何か差が出る可能性? 6};

DataGrid.AutoGeneratedColumns イベント (System.Windows.Controls) | Microsoft Learn

できる前に判断するほうがより良いか?
DataGrid.AutoGeneratingColumn イベント (System.Windows.Controls) | Microsoft Learn

あるいは自前でDataGridColumnを追加していくか?
WPF:DataGridにList<Dictionary<string, object>>をbindする - きよくらの備忘録

類似の事例が見つからず、参考にできませんでした。

確かに全然情報がないですね(dynamicでやってる人が珍しいのか?

IDynamicMetaObjectProviderTypeDescriptionProvider両方適用してしまい、2重になってしまうのかもしれません(特に検証したわけではないが^^;
support the descriptor (component-model) API by mgravell · Pull Request #1216 · DapperLib/Dapper

どちらかを簡単につぶせればいいんですが思いつきませんでした...

GetTypeDescriptorGetExtendedTypeDescriptorで、同じものを返しているのが原因でした。
Dapper/Dapper/SqlMapper.DapperRow.Descriptor.cs#L14 · DapperLib/Dapper

TypeDescriptionProvider.GetExtendedTypeDescriptor(Object) メソッド (System.ComponentModel) | Microsoft Learn

TypeDescriptionProviderを上書きすることも可能ですがあまりに胡散臭いですね^^;

cs

1public partial class MainWindow : Window 2{ 3 class DapperRowTypeDescriptionProvider : TypeDescriptionProvider 4 { 5 public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) 6 { 7 var assembly = Assembly.GetAssembly(typeof(SqlMapper)); 8 var type = assembly.GetType("Dapper.SqlMapper+DapperRow+DapperRowTypeDescriptor"); 9 return (ICustomTypeDescriptor)Activator.CreateInstance(type, instance); 10 } 11 // これがあると2重が再現(どちらを生かすべきかはよくわからんが) 12 //public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) 13 // => GetExtendedTypeDescriptor(instance); 14 } 15 16 public MainWindow() 17 { 18 InitializeComponent(); 19 20 var assembly = Assembly.GetAssembly(typeof(SqlMapper)); 21 var type = assembly.GetType("Dapper.SqlMapper+DapperRow"); 22 TypeDescriptor.AddProvider(new DapperRowTypeDescriptionProvider(), type); 23 } 24}

TypeDescriptor.AddProvider メソッド (System.ComponentModel) | Microsoft Learn

個人的には間違っていると思うので、Issueを上げれば修正されるとは思います(が、私は使わないのでやる気はないです^^;

「CS0206 参照を返さないプロパティまたはインデクサーを out 値または ref 値として使用することはできません」
とエラーが表示される

_DataRowsをフィールドにしてください^^

cs

1private ObservableCollection<dynamic> _DataRows; // { get; set; }

投稿2025/11/25 13:50

編集2025/11/25 21:30
TN8001

総合スコア10220

Hiro987654

2025/11/26 06:16

回答ありがとうございます。 TypeDescriptionProviderの上書きを試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
TN8001

2025/11/26 06:44

> TypeDescriptionProviderの上書きを試したところ問題が解決しました! 👍 DapperRowもDapperRowTypeDescriptorもprivateで名前変更等されても文句は言えません。 現状はうまくいきますが、今後も動くかは保証できない点にご留意ください。
Hiro987654

2025/11/26 08:56

>DapperRowもDapperRowTypeDescriptorもprivateで名前変更等されても文句は言えません。 >現状はうまくいきますが、今後も動くかは保証できない点にご留意ください。 了解しました。今後Dapperが更新されたときに注意するポイントですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問