このトピックは xamPivotGrid コントロール内でデータ セルの編集を有効化し、データ ソースを修正するために編集のイベントを処理する方法を説明します。
このトピックは以下のように構成されています。
セル編集機能によりユーザーは xamPivotGrid コントロールの特定データ セルの値を編集できるようになります。セル編集を有効化するために、開発者は次のステップを実行する必要があります。
AllowCellEdit プロパティを有効化して xamPivotGrid コントロールのセル編集を有効化します。
EditableMeasures コレクションで編集が許されているメジャーを指定します。
CellEdited イベント用のハンドラーでデータのソースを更新し、基本のデータ ソースが xamPivotGrid コントロールのデータ セル内での変更を反映するようにします。
セル編集機能が有効化された場合、セル編集を実行するためにユーザーは xamPivotGrid コントロールのデータ セルをクリックしてセル編集モードに入り、その後特定のデータ セルに新しい値を入力します。
図 1 - データ セルの編集モードでの xamPivotGrid コントロール
表 1 - xamPivotGrid コントロールのセル編集機能で使用されるモジュールのリスト
このセクションは xamPivotGrid コントロール内でデータ セルの編集を有効化し、データ ソースを修正するために編集のイベントを処理する方法の手順を提供します。
AllowCellEdit プロパティを使用して xamPivotGrid コントロールのセル編集を有効化します。
XAML の場合:
<ig:XamPivotGrid x:Name="PivotGrid" > <ig:XamPivotGrid.EditSettings> <ig:EditSettings AllowCellEdit="True" EditableMeasures=""/> </ig:XamPivotGrid.EditSettings> </ig:XamPivotGrid>
Visual Basic の場合:
Imports Infragistics.Controls.Grids Imports Infragistics.Olap ... Me.PivotGrid.EditSettings = New EditSettings() Me.PivotGrid.EditSettings.AllowCellEdit = True
C# の場合:
using Infragistics.Controls.Grids; using Infragistics.Olap; ... this.PivotGrid.EditSettings = new EditSettings(); this.PivotGrid.EditSettings.AllowCellEdit = true;
EditableMeasures コレクションで編集が許されているメジャーを指定します。この構成はコード ビハインドでのみ使用可能です。
Visual Basic の場合:
Imports System.Collections.Specialized Imports Infragistics.Olap Imports Infragistics.Controls.Grids ... ' メジャーがデータ ソースで作成された時に編集可能なメジャーを追加 AddHandler Me.PivotGrid.DataSource.Measures.CollectionChanged, AddressOf OnMeasuresCollectionChanged ... Private Sub OnMeasuresCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs) Select Case e.Action Case NotifyCollectionChangedAction.Add For Each mvm As IMeasureViewModel In e.NewItems If mvm.Caption <> "Amount of sale" Then Me.pivotGrid.EditSettings.EditableMeasures.Add(mvm.Measure) End If If mvm.Caption = "Unit price" Then Me.pivotGrid.DataSource.SetMeasureAggregator(DirectCast(mvm, IMeasureViewModel), AggregationHelper.GetDefaultAverageAggregator(GetType(Double))) End If Next Exit Select Case NotifyCollectionChangedAction.Remove For Each mvm As IMeasureViewModel In e.OldItems Me.pivotGrid.EditSettings.EditableMeasures.Remove(mvm.Measure) Next Exit Select End Select End Sub
C# の場合:
using System.Collections.Specialized; using Infragistics.Olap; using Infragistics.Controls.Grids; ... // メジャーがデータ ソースで作成された時に編集可能なメジャーを追加 this.PivotGrid.DataSource.Measures.CollectionChanged += OnMeasuresCollectionChanged; ... void OnMeasuresCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (IMeasureViewModel mvm in e.NewItems) { if (mvm.Caption != "Amount of sale") this.pivotGrid.EditSettings.EditableMeasures.Add(mvm.Measure); if (mvm.Caption == "Unit price") { this.pivotGrid.DataSource.SetMeasureAggregator( (IMeasureViewModel)mvm, AggregationHelper.GetDefaultAverageAggregator(typeof(double)) ); } } break; case NotifyCollectionChangedAction.Remove: foreach (IMeasureViewModel mvm in e.OldItems) { this.pivotGrid.EditSettings.EditableMeasures.Remove(mvm.Measure); } break; } }
CellEdited イベント用のハンドラーでデータのソースを更新し、基本のデータ ソースが xamPivotGrid コントロールのデータ セル内での変更を反映するようにします。
Visual Basic の場合:
Imports Infragistics.Samples.Data.Models ' SalesDataSamples Imports Infragistics.Olap.Data Imports Infragistics.Olap.FlatData ... AddHandler Me.PivotGrid.CellEdited, AddressOf OnPivotGridCellEdited ... Private Sub OnPivotGridCellEdited(sender As Object, e As PivotCellEditedEventArgs) Dim newValue As Double = [Double].Parse(e.EditedValue.ToString()) Dim indexes As List(Of Integer) = DirectCast(Me.PivotGrid.DataSource, FlatDataSource).GetCellItemsIndexes(TryCast(e.Cell.Data, ICell)) If e.Measure.Caption = "Units sold" Then Dim sale As Sale For Each index As Integer In indexes sale = TryCast(DirectCast(Me.PivotGrid.DataSource, FlatDataSource).GetRecord(index), Sale) If sale IsNot Nothing Then sale.NumberOfUnits = 0 End If Next sale = TryCast(DirectCast(Me.PivotGrid.DataSource, FlatDataSource).GetRecord(indexes(0)), Sale) If sale IsNot Nothing Then sale.NumberOfUnits = CInt(Math.Truncate(newValue)) End If Else For Each index As Integer In indexes Dim sale As Sale = TryCast(DirectCast(Me.PivotGrid.DataSource, FlatDataSource).GetRecord(index), Sale) If sale IsNot Nothing Then sale.UnitPrice = newValue End If Next End If Me.PivotGrid.DataSource.RefreshGrid() End Sub
C# の場合:
using Infragistics.Samples.Data.Models; // SalesDataSample using Infragistics.Olap.Data; using Infragistics.Olap.FlatData; ... this.PivotGrid.CellEdited += OnPivotGridCellEdited; ... void OnPivotGridCellEdited(object sender, PivotCellEditedEventArgs e) { double newValue = Double.Parse(e.EditedValue.ToString()); List<int> indexes = ((FlatDataSource)this.PivotGrid.DataSource) .GetCellItemsIndexes(e.Cell.Data as ICell); if (e.Measure.Caption == "Units sold") { Sale sale; foreach (int index in indexes) { sale = ((FlatDataSource)this.PivotGrid.DataSource).GetRecord(index) as Sale; if (sale != null) sale.NumberOfUnits = 0; } sale = ((FlatDataSource)this.PivotGrid.DataSource).GetRecord(indexes[0]) as Sale; if (sale != null) sale.NumberOfUnits = (int)newValue; } else { foreach (int index in indexes) { Sale sale = ((FlatDataSource)this.PivotGrid.DataSource).GetRecord(index) as Sale; if (sale != null) sale.UnitPrice = newValue; } } this.PivotGrid.DataSource.RefreshGrid(); }
xamPivotGrid コントロールのデータ セルにエンドユーザーが入力できる値を制限したい場合があります。これは CellEditing イベントが発生した時に値の検証を行うことで可能になります。
図 2 - ユーザー入力の検証を行う xamPivotGrid コントロール
以下はデータ セルの編集を 0 から 10000 の間の値に制限する例です。独自のデータ検証ルールを追加し、以下に示したものと同様に実装することができます。
ユーザー入力の検証を行う ValueValidation クラスを追加します。
Visual Basic の場合:
Imports System.Windows.Controls Imports System.Globalization ... ''' <summary> ''' Value プロパティが正しい値をもっているかどうかをチェックする検証ルールをオーバーライドするオブジェクトを表す。 ''' </summary> Public Class ValueValidation Inherits ValidationRule Public Property Value() As Object Get Return _value End Get Set _value = Value End Set End Property Private _value As Object Public Property Min() As Integer Get Return _min End Get Set _min = Value End Set End Property Private _min As Integer Public Property Max() As Integer Get Return _max End Get Set _max = Value End Set End Property Private _max As Integer Public Overrides Function Validate(value As Object, cultureInfo As CultureInfo) As ValidationResult Dim result As String = ValidateValue(value) Return New ValidationResult(result Is Nothing, result) End Function Public Function ValidateValue(value As Object) As String If String.IsNullOrEmpty(DirectCast(value, [String])) Then Return "Value cannot be null!" End If Try Dim newValue As Integer = Int32.Parse(DirectCast(value, [String])) If (newValue < Me.Min) OrElse (newValue > Me.Max) Then Return "Value is out of the range: " & Me.Min & " - " & Me.Max & "." End If Catch e As Exception Return "Value has illegal characters or " + e.Message End Try Return Nothing End Function End Class
C# の場合:
using System.Windows.Controls; using System.Globalization; ... /// <summary> /// Value プロパティが正しい値をもっているかどうかをチェックする検証ルールをオーバーライドするオブジェクトを表す。 /// </summary> public class ValueValidation : ValidationRule { public object Value { get; set; } public int Min { get; set; } public int Max { get; set; } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { string result = ValidateValue(value); return new ValidationResult(result == null, result); } public string ValidateValue(object value) { if (string.IsNullOrEmpty((String)value)) { return "Value cannot be null!"; } try { int newValue = Int32.Parse((String)value); if ((newValue < this.Min) || (newValue > this.Max)) { return "Value is out of the range: " + this.Min + " - " + this.Max + "."; } } catch (Exception e) { return "Value has illegal characters or " + e.Message; } return null; } }
xamPivotGrid コントロールの CellEditing イベントに関する検証エラーの扱いを実装します。
Visual Basic の場合:
Imports System.Windows.Controls Imports Infragistics.Controls.Grids ... AddHandler Me.PivotGrid.CellEditing, AddressOf OnPivotGridCellEditing ... Private Sub OnPivotGridCellEditing(sender As Object, e As PivotCellEditingEventArgs) If e.Measure.Name = "NumberOfUnits" Then Dim evh As EventHandler(Of ValidationErrorEventArgs) = AddressOf OnValueValidationError Validation.AddErrorHandler(Me, evh) Dim obj As New ValueValidation() With { _ Key .Value = e.EditedValue _ } Dim b As New Binding("Value") b.Source = obj b.ValidationRules.Add(New ValueValidation() With { _ Key .Min = 0, _ Key .Max = 10000 _ }) b.ValidatesOnDataErrors = InlineAssignHelper(b.ValidatesOnExceptions, InlineAssignHelper(b.NotifyOnValidationError, True)) e.Editor.SetBinding(TextBox.TextProperty, b) e.Editor.GetBindingExpression(TextBox.TextProperty).UpdateSource() ' ここかまたは OnValueValidationError エラーハンドラーで検証エラーを取り扱う If Validation.GetHasError(e.Editor) Then e.Cancel = True Dim errors As ReadOnlyObservableCollection(Of ValidationError) = Validation.GetErrors(e.Editor) For Each [error] As var In errors ' ユーザーに各検証エラーについて通知 Dim message As String = "Invalid value detected: " & Convert.ToString(e.Editor.Text) message += Environment.NewLine + [error].ErrorContent MessageBox.Show(message, "Validation Error", MessageBoxButton.OK) Next End If Validation.RemoveErrorHandler(Me, evh) End If End Sub Private Sub OnValueValidationError(sender As Object, e As ValidationErrorEventArgs) If e.Action = ValidationErrorEventAction.Added Then ' ユーザーに検証エラーについて通知 Dim message As String = e.[Error].ErrorContent.ToString() MessageBox.Show(message, "Validation Error", MessageBoxButton.OK) End If End Sub
C# の場合:
using System.Windows.Controls; using Infragistics.Controls.Grids; ... this.PivotGrid.CellEditing += OnPivotGridCellEditing; ... private void OnPivotGridCellEditing(object sender, PivotCellEditingEventArgs e) { if (e.Measure.Name == "NumberOfUnits") { EventHandler<ValidationErrorEventArgs> evh = OnValueValidationError; Validation.AddErrorHandler(this, evh); ValueValidation obj = new ValueValidation { Value = e.EditedValue }; Binding b = new Binding("Value"); b.Source = obj; b.ValidationRules.Add(new ValueValidation { Min = 0, Max = 10000 }); b.ValidatesOnDataErrors = b.ValidatesOnExceptions = b.NotifyOnValidationError = true; e.Editor.SetBinding(TextBox.TextProperty, b); e.Editor.GetBindingExpression(TextBox.TextProperty).UpdateSource(); // ここかまたは OnValueValidationError エラーハンドラーで検証エラーを取り扱う if (Validation.GetHasError(e.Editor)) { e.Cancel = true; ReadOnlyObservableCollection<ValidationError> errors = Validation.GetErrors(e.Editor); foreach (var error in errors) { // ユーザーに各検証エラーについて通知 string message = "Invalid value detected: " + e.Editor.Text; message += Environment.NewLine + error.ErrorContent; MessageBox.Show(message, "Validation Error", MessageBoxButton.OK); } } Validation.RemoveErrorHandler(this, evh); } } private void OnValueValidationError(object sender, ValidationErrorEventArgs e) { if (e.Action == ValidationErrorEventAction.Added) { // ユーザーに検証エラーについて通知 string message = e.Error.ErrorContent.ToString(); MessageBox.Show(message, "Validation Error", MessageBoxButton.OK); } }
関連トピック