このトピックは 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);
}
}
関連トピック