前提
お世話になっております。
C# WPF で、リストのデータを表示するため、DataGridコントロールを配置しています。
DataGridコントロールのデータソースには、自作クラスのインスタンスが格納されたObservableCollectionを使用します。
配置されるViewは、PrismのDialogServiceで呼び出したカスタムダイアログのUserControlです。
実現したいこと
DataGridの編集時、セル・行それぞれコミットする際、無効な値(重複など)が含まれている場合にコミットをせずに編集状態を続行したい。
また、コミットを取り消された際、ViewModel側で処理を走らせたいので、できればXamlとViewModelクラスで完結させたい(MVVMの考え方として正しいかどうかはわかりません。Viewに関わる処理ならコードビハインドで処理を行っても良いのか?)
該当のソースコード
C#
1using Prism.Commands; 2using Prism.Mvvm; 3using Prism.Services.Dialogs; 4using Reactive.Bindings; 5using Reactive.Bindings.ObjectExtensions; 6using System; 7using System.Collections.Generic; 8using System.Collections.ObjectModel; 9using System.Linq; 10 11namespace EditDialog.ViewModels 12{ 13 public class EditDeviceDialogViewModel : BindableBase, IDialogAware 14 { 15 public IDialogService _dialogService; 16 17 /// <summary> 18 /// 表示されるクラス 19 /// </summary> 20 public ReactiveProperty<ExampleClass> _exampleClass { get; } = new(); 21 22 /// <summary> 23 /// Exampleインスタンスを格納するBinding用のObservableCollection 24 /// </summary> 25 public ObservableCollection<ExampleClass> ExampleClasses 26 { 27 get { return this._exampleClass; } 28 } 29 30 public DelegateCommand EndEditingRowCommand { get; private set; } 31 32 public EditDeviceDialogViewModel(IDialogService dialogService) 33 { 34 _dialogService = dialogService; 35 EndEditingRowCommand = new DelegateCommand(EndEditingRow); 36 37 // データソースからリストを読み出し、ExampleClassesに格納する処理 38 } 39 40 void EndEditingRow() 41 { 42 // 編集のコミットとコマンドを紐付ける事はできるが、コミットの取り消し動作を実装できなかった 43 } 44 45 public string Title => "Example"; 46 47 public event Action<IDialogResult>? RequestClose; 48 49 public bool CanCloseDialog() 50 { 51 return true; 52 } 53 54 public void OnDialogClosed() 55 { 56 } 57 58 public void OnDialogOpened(IDialogParameters parameters) 59 { 60 } 61 } 62 63 // モデルクラス 64 public record ExampleClass 65 { 66 public int Id { get; set; } 67 68 public string? ExampleName { get; set; } 69 70 public bool Enabled { get; set; } 71 } 72}
Xaml
1<UserControl x:Class="ExampleProject.Views.EditDialog" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:bh="http://schemas.microsoft.com/xaml/behaviors" 5 xmlns:prism="http://prismlibrary.com/" 6 prism:ViewModelLocator.AutoWireViewModel="True"> 7 <prism:Dialog.WindowStyle> 8 <Style TargetType="Window"> 9 <Setter Property="Height" Value="700"/> 10 <Setter Property="Width" Value="1200"/> 11 <Setter Property="ResizeMode" Value="NoResize"/> 12 </Style> 13 </prism:Dialog.WindowStyle> 14 <Grid> 15 <DataGrid ItemsSource="{Binding ExampleList}" AutoGenerateColumns="False" > 16 <bh:Interaction.Triggers> 17 <bh:EventTrigger EventName="RowEditEnding"> 18 <bh:InvokeCommandAction Command="{Binding EndEditingRowCommand}"/> 19 </bh:EventTrigger> 20 </bh:Interaction.Triggers> 21 <DataGrid.Columns> 22 <DataGridTextColumn Header="id" Binding="{Binding Id}" Width="Auto" /> 23 <DataGridTextColumn Header="example__name" Binding="{Binding ExampleName}" Width="Auto"/> 24 <DataGridCheckBoxColumn Header="enabled" Binding="{Binding Enabled}" Width="Auto"/> 25 </DataGrid.Columns> 26 </DataGrid> 27</Grid> 28</UserControl> 29
試したこと
DataGridのCellEditEnding、及びRowEditEndingイベントをコマンドにバインドしてコミットを検知する方法を考えましたが、検知はできてもコミット取り消し動作を実装する方法までたどり着けませんでした。
補足情報(FW/ツールのバージョンなど)
Visual Studio 2022
C# 10.0
Prism.Unity 8.1.97
ReactiveProperty.WPF 9.4.1
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/03/14 11:57
2024/03/14 12:57
2024/03/14 22:25