質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Q&A

解決済

1回答

7739閲覧

ReactivePropertyでDataGridのItemsSourceの内容が変更された時にDataGridの表示を更新したい

as00000

総合スコア21

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

0グッド

0クリップ

投稿2021/06/28 01:05

前提・実現したいこと

[C#] [.NET Core3.1] [Prism(Unity)] [ReactiveProperty]を使って
DataGridにcsvファイルの中身を表示し
Buttonを押すとcsvファイル内の'数量'を加減するプログラムを作っていますが
Buttonを押してもDataGridの表示が変更されません

・DataGridのItemsSourceの中身が変わったら画面が更新される方法
をご教示頂けませんでしょうか

発生している問題

Debugで中身を確認すると
数値は変更されていますが、表示に反映されていない様なので
Bindingの問題ではないかと推測しています

該当のソースコード

SubUserControl.xaml

xaml

1<UserControl 2 ~ 略 ~ 3 xmlns:prism="http://prismlibrary.com/"> 4 5 6 <i:Interaction.Triggers> 7 <i:EventTrigger EventName="Loaded"> 8 <prism:InvokeCommandAction Command="{Binding WindowLoadedCommand}" /> 9 </i:EventTrigger> 10 </i:Interaction.Triggers> 11 12 <Grid> 13 14 <Grid.ColumnDefinitions> 15 <ColumnDefinition Width="5*" /> 16 <ColumnDefinition Width="1*" /> 17 </Grid.ColumnDefinitions> 18 19 <DataGrid 20 Grid.Column="0" 21 AutoGenerateColumns="False" 22 IsReadOnly="True" 23 SelectionMode="Single" 24 ItemsSource="{Binding DetailList, Mode=TwoWay}" 25 SelectedItem="{Binding DetailListSelectedItem.Value, Mode=TwoWay}"> 26 27 28 <DataGrid.Columns> 29 <DataGridTextColumn 30 x:Name="Classification" 31 Width="3*" 32 Binding="{Binding Classification}" 33 Header="種類" /> 34 35~ 中略 ~ 36 37 <DataGridTextColumn 38 x:Name="Quantity" 39 Width="1*" 40 Binding="{Binding Quantity, Mode=TwoWay}" 41 Header="数量" /> 42 <DataGridTextColumn 43 x:Name="Remark" 44 Width="3*" 45 Binding="{Binding Remark}" 46 Header="備考" /> 47 48~ 中略 ~ 49 </DataGrid.Columns> 50 51 </DataGrid> 52 53 <StackPanel Grid.Column="1" Orientation="Vertical"> 54 55 <StackPanel Orientation="Horizontal"> 56 <Button Content="-" /> ←【未実装】 57 58 <Button 59 Command="{Binding PlusCommand}" 60 Content="+" /> 61 </StackPanel> 62 63 <Button 64 Command="{Binding OnConfirmCommand}" 65 Content="確定" /> 66 </StackPanel> 67 68 69 </Grid> 70</UserControl> 71

xamlのイメージ

SubUserControlModel.cs

C#

1namespace Sample.Models 2{ 3 public class SubUserControlModel : BindableBase, ISubUserControlModel 4 { 5 6 public SubUserControlModel() 7 { 8 this.DetailList = new ObservableCollection<FileDetailItem>(); 9 } 10 11 // DataGridに表示する内容 12 private ObservableCollection<FileDetailItem> _DetailList; 13 public ObservableCollection<FileDetailItem> DetailList 14 { 15 get { return _DetailList; } 16 set { SetProperty(ref _DetailList, value); } 17 } 18 19 20 // csvファイルのパスなどを保持しているクラス 21 public FileListItem FileListSelectedItem { get; set; } 22 23 24 // 現在選択中のItem 25 private FileDetailItem _detailListSelectedItem; 26 public FileDetailItem DetailListSelectedItem 27 { 28 get { return _detailListSelectedItem; } 29 set { SetProperty(ref _detailListSelectedItem, value); } 30 } 31 32 33 // DialogのTitleにセットするstringを返す 34 public string SetDialogTitle(FileListItem fileListItem) 35 { 36 ~ 略 ~ 37 } 38 39 40 // 画面起動時に実行するコード 41 public void OnWindowloaded(IDialogParameters parameters) 42 { 43 if (parameters != null) 44 { 45 46 // パラメータの取得 47 this.FileListSelectedItem = parameters.GetValue<FileListItem>("FileListSelectedItem"); 48 var Rate01 = parameters.GetValue<double>("Rate01"); 49 var Rate02 = parameters.GetValue<double>("Rate02"); 50 var MinimumNumber = parameters.GetValue<double>("MinimumNumber"); 51 var SpacerMultiple = parameters.GetValue<double>("SpacerMultiple"); 52 var AfterDecimalPointFunc = parameters?.GetValue<Func<double, double>>("AfterDecimalPoint"); 53 54 this.DetailList.Clear(); 55 56 if (this.FileListSelectedItem != null) 57 { 58 // pnlファイルの内容を取得+表示 59 if (File.Exists(this.FileListSelectedItem.FilePath)) 60 { 61 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 62 using StreamReader streamReader 63 = new StreamReader(this.FileListSelectedItem.FilePath, Encoding.GetEncoding("Shift_JIS")); 64 { 65 66 var line = ""; 67 while ((line = streamReader.ReadLine()) != null) 68 { 69 var item = new FileDetailItem(line); 70 71 if (!item.IsModifiedData) // 書き換えてないデータだけ書き換える 72 { 73 var originalQuantity = item.Quantity; 74 int modifiedQuantity = 0; 75 var remarkString = ""; 76 77 switch (int.Parse(item.Material)) 78 { 79 case 1: 80 modifiedQuantity 81 = GetAddedQuantity(originalQuantity, Rate01, MinimumNumber, AfterDecimalPointFunc); 82 remarkString = "[←" + originalQuantity + "]" + item.Remark; 83 break; 84 85 ~ 略 ~ 86 87 88 default: 89 break; 90 } 91 92 // 数量と備考を書き換え 93 item.Quantity = modifiedQuantity; 94 item.Remark = remarkString; 95 } 96 97 this.DetailList.Add(item); 98 } 99 } 100 } 101 else 102 { 103 this.DetailList.Add(new FileDetailItem("")); 104 } 105 } 106 } 107 } 108 109 110 public void Plus() 111 { 112 // 選択されているItemをインクリメントするメソッド実行 113 this.DetailListSelectedItem.Plus(); 114 115      【↑ 内容が変わったタイミングでDataGridが更新されて欲しい】 116 117 } 118 119 120 121 // DataGridに表示されている内容をファイルに書き込み 122 public void OnConfirm() 123 { 124 ~ 略 ~ 125 } 126 127 128 ~ 略 ~ 129 } 130} 131

SubUserControlViewModel.cs

C#

1namespace Sample.ViewModels 2{ 3 class SubUserControlViewModel : BindableBase, IDisposable, IDialogAware 4 5 { 6 private CompositeDisposable Disposable { get; } = new CompositeDisposable(); 7 public void Dispose() => this.Disposable.Dispose(); 8 9 10 MainWindowModel _mainWindowModel; 11 SubUserControlModel _subUserControlModel; 12 13 14 public ReadOnlyReactiveCollection<FileDetailItem> DetailList { get; set; } 15 public ReactiveProperty<FileDetailItem> DetailListSelectedItem { get; set; } = new ReactiveProperty<FileDetailItem>(); 16 public ReactiveProperty<string> WindowTitle { get; set; } = new ReactiveProperty<string>(); 17 18 public ReactiveCommand WindowLoadedCommand { get; } = new ReactiveCommand(); 19 public ReactiveCommand OnConfirmCommand { get; } = new ReactiveCommand(); 20 21 public ReactiveCommand PlusCommand { get; } = new ReactiveCommand(); 22 23 24 25 public SubUserControlViewModel(ISubUserControlModel iSubUserControlModel, IMainWindowModel iMainWindowModel) 26 { 27 28 this._subUserControlModel = (SubUserControlModel)iSubUserControlModel; 29 this._mainWindowModel = (MainWindowModel)iMainWindowModel; 30 31 this.DetailList = this._subUserControlModel.DetailList.ToReadOnlyReactiveCollection(); 32 this.DetailListSelectedItem = this._subUserControlModel.ToReactivePropertyAsSynchronized(x => x.DetailListSelectedItem); 33 34 35 this.PlusCommand.Subscribe(_ => _subUserControlModel.Plus()); 36 this.OnConfirmCommand.Subscribe(_ => _subUserControlModel.OnConfirm()); 37 38 } 39 40 41 42 43 #region IDialogAwareのメンバ 44 45 public string Title => _subUserControlModel.SetDialogTitle(this._mainWindowModel.FileListSelectedItem); 46 47 ~ 略 ~ 48 #endregion 49 50 51 } 52} 53

FileDetailItem.cs (DataGridに表示するItem

C#

1namespace Sample.Models 2{ 3 public class FileDetailItem 4 { 5 6 public string Classification { get; } // 種類 7~ 中略 ~ 8 public int Quantity { get; set; } // 数量 9 public string Remark { get; set; } // 備考 10~ 中略 ~ 11 public string OriginalCSVstring { get; } 12 public string ModifiedCSVstring 13 { 14 get 15 { 16 return 17 xxx + "," + xxx + "," + xxx + "," + 18 xxx + "," + xxx + "," + xxx + "," + 19 Quantity.ToString() + "," + Remark + "," + xxx + "," + xxx; 20 } 21 } 22 public bool IsModifiedData { get; } 23 24 25 public FileDetailItem(string csvstring) 26 { 27 ~ 略 ~ 28 } 29 30 31 public void Plus() 32 { 33 this.Quantity++; 34 } 35 36 } 37} 38 39

試した事

FileDetailItem.Plus()を実行する度に
DataGrid.Clear → 内容を再読み込みすれば
数量の更新は出来たのですが
再読み込みにより選択項目がリセットされてしまい
+を連続で押す事が出来なくなる為
希望の動作にはなりませんでした

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

FileDetailItem クラスに INotifyPropertyChanged インターフェースを実装して Quantity プロパティで PropertyChanged イベントを発生させるようにしたら表示も更新されると思います。
Prism を使っているのであれば以下のように BindableBase クラスを継承して SetProperty メソッドを使えば自動的に PropertyChanged イベントを発行してくれます。

csharp

1namespace Sample.Models 2{ 3 public class FileDetailItem : BindableBase 4 { 5 6~ 中略 ~ 7 private int _quantity; 8 public int Quantity 9 { 10 get => _quantity; 11 set => SetProperty(ref _quantity, value); 12 } // 数量 13~ 中略 ~ 14 } 15}

投稿2021/06/28 04:21

okazuki0130

総合スコア185

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

as00000

2021/06/28 04:48

教えて頂いた通り、BindableBase クラスを継承→SetProperty メソッドを使用する事で希望通りの動作を行う事が出来ました。 ご教示頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問