SPREAD for WPF 3.0J - GcSpreadSheet > 開発者ガイド > データ検証 > 検証エラーUIのカスタマイズ |
GcSpreadSheetでは、無効な値を入力したときに表示される検証エラーUIの外観を完全にカスタマイズすることができます。外観をカスタマイズするには、DataValidationTemplateで定義されている組み込みのValidationErrorIndicatorを使用するか、要件に基づいて独自で作成することができます。また、組み込みのValidationErrorIndicatorをカスタマイズして、背景色、前景色、境界線の色などを変更するための書式を指定ことができます。
DataValidationTemplateにデータテンプレートが割り当てられている場合、DataValidationTemplateはデータソースに連結されているシートに無効な値を入力する時のエラーメッセージを表示するためにも使用できます。
組み込みの検証エラーインジケーターを使用するには、DataValidationTemplateでデータテンプレートを設定します。データテンプレートに使用されるデータ型はDataValidationContextです。また、 ValidationErrorIndicatorクラスを使用して、検証エラーインジケーターの組み込みスタイルを適用できます。
次の図は、組み込みスタイルが適用された検証エラーインジケーターを示します。デフォルトでは、正しくない値を含むセルの右上隅に赤い三角形が表示されます。
以下のコードは、組み込みの検証エラーインジケーターを使用する方法を示します。
コードのコピー
|
|
---|---|
<Grid> <gss:GcSpreadSheet Margin="5" Grid.Row="0" x:Name="GcSpreadSheet" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" > <gss:GcSpreadSheet.DataValidationTemplate> <DataTemplate DataType="{x:Type gss:DataValidationContext}" > <gss:ValidationErrorIndicator /> </DataTemplate> </gss:GcSpreadSheet.DataValidationTemplate> </gss:GcSpreadSheet> </Grid> |
コードのコピー
|
|
---|---|
// データ検証 IValidation val = GcSpreadSheet.Workbook.ActiveSheet.Cells["B4:B8"].Validation.Add(DataValidationType.List, DataValidationErrorStyle.Stop, DataValidationOperator.Equal, "Valid", ""); val.ShowError = true; val.ShowInput = true; val.ErrorMessage = "エラーメッセージ"; val.ErrorTitle = "タイトルにエラーがあります。"; val.InputMessage = "入力したメッセージです。"; val.InputTitle = "入力したタイトルです。"; // サンプルデータ GcSpreadSheet.Workbook.ActiveSheet.Cells["B4"].Value = "無効"; GcSpreadSheet.Workbook.ActiveSheet.Cells[3, 1].Activate(); GcSpreadSheet.Workbook.ActiveSheet.Cells["B5:B7"].Value = "有効"; GcSpreadSheet.Workbook.ActiveSheet.Cells["B8"].Value = "無効"; GcSpreadSheet.Workbook.ActiveSheet.CircleInvalid(); |
コードのコピー
|
|
---|---|
' データ検証 Dim val As IValidation = GcSpreadSheet.Workbook.ActiveSheet.Cells("B4:B8").Validation.Add(DataValidationType.List, DataValidationErrorStyle.[Stop], DataValidationOperator.Equal, "Valid", "") val.ShowError = True val.ShowInput = True val.ErrorMessage = "エラーメッセージ" val.ErrorTitle = "タイトルにエラーがあります。" val.InputMessage = "入力したメッセージです。" val.InputTitle = "入力したタイトルです。" ' サンプルデータ GcSpreadSheet.Workbook.ActiveSheet.Cells("B4").Value = "無効" GcSpreadSheet.Workbook.ActiveSheet.Cells(3, 1).Activate() GcSpreadSheet.Workbook.ActiveSheet.Cells("B5:B7").Value = "有効" GcSpreadSheet.Workbook.ActiveSheet.Cells("B8").Value = "無効" GcSpreadSheet.Workbook.ActiveSheet.CircleInvalid() |
データテンプレートでValidationErrorIndicatorの属性をカスタマイズすることで、背景色、前景色、境界線の太さ、フォントサイズ、フォントスタイルなどのエラーメッセージのスタイルを変更できます。
次の図は、DataValidationTemplateで定義されている検証エラーインジケーターをカスタマイズして、データソースに連結されているシートに無効な値を入力する時のエラーメッセージを表示する例です。
以下のコードは、組み込みの検証エラーインジケーターをカスタマイズして、連結されているシートにエラーメッセージを表示します。
コードのコピー
|
|
---|---|
<Grid> <gss:GcSpreadSheet x:Name="GcSpreadSheet"> <gss:GcSpreadSheet.DataValidationTemplate> <DataTemplate DataType="{x:Type gss:DataValidationContext}" > <gss:ValidationErrorIndicator Background="SkyBlue" Foreground="Maroon" BorderBrush="Orange" BorderThickness="1"/> </DataTemplate> </gss:GcSpreadSheet.DataValidationTemplate> </gss:GcSpreadSheet> </Grid> |
コードのコピー
|
|
---|---|
public class Employee : INotifyPropertyChanged { int id; string name; DateTime hiredate; DateTime birthday; [Required(ErrorMessage = "Please enter the ID.")] public int ID { set { if (value > 999999999) throw new Exception("ID is too long with 10 numbers or more."); id = value; NotifyPropertyChanged("ID"); } get { return id; } } [Display(ShortName = "Elvy")] public string Name { set { name = value; NotifyPropertyChanged("Name"); } get { return name; } } [Display(ShortName = "Bob")] public DateTime HireDate { set { hiredate = value; NotifyPropertyChanged("HireDate"); } get { return hiredate; } } [Display(ShortName = "Tim")] public DateTime Birthday { set { birthday = value; NotifyPropertyChanged("Birthday"); } get { return birthday; } } public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public class EmployeeCollection : ObservableCollection<Employee> { public EmployeeCollection() { Add(new Employee() { ID = 10200115, Name = "William Thomson", HireDate = DateTime.Parse("2003/12/1"), Birthday = DateTime.Parse("2000/9/17") }); Add(new Employee() { ID = 10200116, Name = "", HireDate = DateTime.Today, Birthday = DateTime.Today.AddYears(-20) }); Add(new Employee() { ID = 10200117, Name = "William Thomson", HireDate = DateTime.Parse("2003/12/1"), Birthday = DateTime.Parse("2000/9/17") }); Add(new Employee() { ID = 10200118, Name = "", HireDate = DateTime.Today, Birthday = DateTime.Today.AddYears(-20) }); Add(new Employee() { ID = 10200119, Name = "", HireDate = DateTime.Today, Birthday = DateTime.Today.AddYears(-20) }); } } |
コードのコピー
|
|
---|---|
Public Class Employee Inherits INotifyPropertyChanged Public id As Integer Public name As String Public hiredate As DateTime Public birthday As DateTime <Required(ErrorMessage:="Please enter the ID.")> Public Property ID1 As Integer Set(ByVal value As Integer) If value > 999999999 Then Throw New Exception("ID is too long with 10 numbers or more.") id = value NotifyPropertyChanged("ID") End Set Get Return id End Get End Property <Display(ShortName:="Elvy")> Public Property Name1 As String Set(ByVal value As String) name = value NotifyPropertyChanged("Name") End Set Get Return name End Get End Property <Display(ShortName:="Bob")> Public Property HireDate1 As DateTime Set(ByVal value As DateTime) hiredate = value NotifyPropertyChanged("HireDate") End Set Get Return hiredate End Get End Property <Display(ShortName:="Tim")> Public Property Birthday1 As DateTime Set(ByVal value As DateTime) birthday = value NotifyPropertyChanged("Birthday") End Set Get Return birthday End Get End Property Public Event PropertyChanged As PropertyChangedEventHandler Protected Sub NotifyPropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub End Class Public Class EmployeeCollection Inherits ObservableCollection(Of Employee) Public Sub New() Add(New Employee() With { .ID = 10200115, .Name = "William Thomson", .HireDate = DateTime.Parse("2003/12/1"), .Birthday = DateTime.Parse("2000/9/17") }) Add(New Employee() With { .ID = 10200116, .Name = "", .HireDate = DateTime.Today, .Birthday = DateTime.Today.AddYears(-20) }) Add(New Employee() With { .ID = 10200117, .Name = "William Thomson", .HireDate = DateTime.Parse("2003/12/1"), .Birthday = DateTime.Parse("2000/9/17") }) Add(New Employee() With { .ID = 10200118, .Name = "", .HireDate = DateTime.Today, .Birthday = DateTime.Today.AddYears(-20) }) Add(New Employee() With { .ID = 10200119, .Name = "", .HireDate = DateTime.Today, .Birthday = DateTime.Today.AddYears(-20) }) End Sub End Class |
カスタム検証エラーインジケーターを作成して、無効な値を入力した際のエラーメッセージを完全にカスタマイズすることができます。また、独自のコントロールを作成して、検証エラーインジケーターとして使用できます。
次の図は、カスタムコントロールを作成して、検証エラーインジケーターとして使用する方法を示します。
次のコードは、エラーメッセージを表示するためのカスタムコントロールを作成します。
コードのコピー
|
|
---|---|
public class MyCustomValidationIndicatorControl : Control { public static readonly DependencyProperty IsActivedProperty = DependencyProperty.Register("IsActived", typeof(bool), typeof(MyCustomValidationIndicatorControl), new UIPropertyMetadata(UpdateTooltip)); public static readonly DependencyProperty IsEditErrorProperty = DependencyProperty.Register("IsEditError", typeof(bool), typeof(MyCustomValidationIndicatorControl), new UIPropertyMetadata(UpdateTooltip)); public static readonly DependencyProperty IsInvalidProperty = DependencyProperty.Register("IsInvalid", typeof(bool), typeof(MyCustomValidationIndicatorControl), new UIPropertyMetadata()); public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(MyCustomValidationIndicatorControl), new UIPropertyMetadata()); public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(MyCustomValidationIndicatorControl), new UIPropertyMetadata()); public bool IsInvalid { get { return (bool)GetValue(IsInvalidProperty); } internal set { SetValue(IsInvalidProperty, value); } } public bool IsActived { get { return (bool)GetValue(IsActivedProperty); } internal set { SetValue(IsActivedProperty, value); } } public bool IsEditError { get { return (bool)GetValue(IsEditErrorProperty); } internal set { SetValue(IsEditErrorProperty, value); } } public string Message { get { return (string)GetValue(MessageProperty); } internal set { SetValue(MessageProperty, value); } } public string Title { get { return (string)GetValue(TitleProperty); } internal set { SetValue(TitleProperty, value); } } public MyCustomValidationIndicatorControl() { this.IsTabStop = false; Binding binding = new Binding("IsFocused"); this.SetBinding(MyCustomValidationIndicatorControl.IsActivedProperty, binding); Binding binding2 = new Binding("IsEditError"); this.SetBinding(MyCustomValidationIndicatorControl.IsEditErrorProperty, binding2); Binding binding3 = new Binding("IsInvalid"); this.SetBinding(MyCustomValidationIndicatorControl.IsInvalidProperty, binding3); } private static void UpdateTooltip(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { MyCustomValidationIndicatorControl validationErrorIndicator = dependencyObject as MyCustomValidationIndicatorControl; DataValidationContext dataValidationContext = validationErrorIndicator.DataContext as DataValidationContext; if (dataValidationContext != null && validationErrorIndicator.IsActived) { if (!string.IsNullOrEmpty(dataValidationContext.EditingErrorException)) { validationErrorIndicator.Message = dataValidationContext.EditingErrorException; validationErrorIndicator.Title = string.Empty; } else { validationErrorIndicator.Message = (validationErrorIndicator.IsEditError) ? (dataValidationContext.ShowError ? dataValidationContext.ErrorMessage : string.Empty) : (dataValidationContext.ShowInput ? dataValidationContext.InputMessage : string.Empty); validationErrorIndicator.Title = (validationErrorIndicator.IsEditError) ? (dataValidationContext.ShowError ? dataValidationContext.ErrorTitle : string.Empty) : (dataValidationContext.ShowInput ? dataValidationContext.InputTitle : string.Empty); } } } protected override void OnVisualParentChanged(DependencyObject oldParent) { if (oldParent != null && !this.IsDescendantOf(oldParent)) { this.IsActived = false; } base.OnVisualParentChanged(oldParent); } |
コードのコピー
|
|
---|---|
Public Class MyCustomValidationIndicatorControl Inherits Control Public Shared ReadOnly IsActivedProperty As DependencyProperty = DependencyProperty.Register("IsActived", GetType(Boolean), GetType(MyCustomValidationIndicatorControl), New UIPropertyMetadata(AddressOf UpdateTooltip)) Public Shared ReadOnly IsEditErrorProperty As DependencyProperty = DependencyProperty.Register("IsEditError", GetType(Boolean), GetType(MyCustomValidationIndicatorControl), New UIPropertyMetadata(AddressOf UpdateTooltip)) Public Shared ReadOnly IsInvalidProperty As DependencyProperty = DependencyProperty.Register("IsInvalid", GetType(Boolean), GetType(MyCustomValidationIndicatorControl), New UIPropertyMetadata()) Public Shared ReadOnly MessageProperty As DependencyProperty = DependencyProperty.Register("Message", GetType(String), GetType(MyCustomValidationIndicatorControl), New UIPropertyMetadata()) Public Shared ReadOnly TitleProperty As DependencyProperty = DependencyProperty.Register("Title", GetType(String), GetType(MyCustomValidationIndicatorControl), New UIPropertyMetadata()) Public Property IsInvalid As Boolean Get Return CBool(GetValue(IsInvalidProperty)) End Get Friend Set(ByVal value As Boolean) SetValue(IsInvalidProperty, value) End Set End Property Public Property IsActived As Boolean Get Return CBool(GetValue(IsActivedProperty)) End Get Friend Set(ByVal value As Boolean) SetValue(IsActivedProperty, value) End Set End Property Public Property IsEditError As Boolean Get Return CBool(GetValue(IsEditErrorProperty)) End Get Friend Set(ByVal value As Boolean) SetValue(IsEditErrorProperty, value) End Set End Property Public Property Message As String Get Return CStr(GetValue(MessageProperty)) End Get Friend Set(ByVal value As String) SetValue(MessageProperty, value) End Set End Property Public Property Title As String Get Return CStr(GetValue(TitleProperty)) End Get Friend Set(ByVal value As String) SetValue(TitleProperty, value) End Set End Property Public Sub New() Me.IsTabStop = False Dim binding As Binding = New Binding("IsFocused") Me.SetBinding(MyCustomValidationIndicatorControl.IsActivedProperty, binding) Dim binding2 As Binding = New Binding("IsEditError") Me.SetBinding(MyCustomValidationIndicatorControl.IsEditErrorProperty, binding2) Dim binding3 As Binding = New Binding("IsInvalid") Me.SetBinding(MyCustomValidationIndicatorControl.IsInvalidProperty, binding3) End Sub Private Shared Sub UpdateTooltip(ByVal dependencyObject As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) Dim validationErrorIndicator As MyCustomValidationIndicatorControl = TryCast(dependencyObject, MyCustomValidationIndicatorControl) Dim dataValidationContext As DataValidationContext = TryCast(validationErrorIndicator.DataContext, DataValidationContext) If dataValidationContext IsNot Nothing AndAlso validationErrorIndicator.IsActived Then If Not String.IsNullOrEmpty(dataValidationContext.EditingErrorException) Then validationErrorIndicator.Message = dataValidationContext.EditingErrorException validationErrorIndicator.Title = String.Empty Else validationErrorIndicator.Message = If((validationErrorIndicator.IsEditError), (If(dataValidationContext.ShowError, dataValidationContext.ErrorMessage, String.Empty)), (If(dataValidationContext.ShowInput, dataValidationContext.InputMessage, String.Empty))) validationErrorIndicator.Title = If((validationErrorIndicator.IsEditError), (If(dataValidationContext.ShowError, dataValidationContext.ErrorTitle, String.Empty)), (If(dataValidationContext.ShowInput, dataValidationContext.InputTitle, String.Empty))) End If End If End Sub Protected Overrides Sub OnVisualParentChanged(ByVal oldParent As DependencyObject) If oldParent IsNot Nothing AndAlso Not Me.IsDescendantOf(oldParent) Then Me.IsActived = False End If MyBase.OnVisualParentChanged(oldParent) End Sub End Class |
以下のコードは、カスタムコントロールを使用するためにデータテンプレートを作成します。
コードのコピー
|
|
---|---|
<Grid> <gss:GcSpreadSheet x:Name="GcSpreadSheet" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" > <gss:GcSpreadSheet.Resources> <ControlTemplate x:Key="ValidationToolTipTemplate" TargetType="ToolTip"> <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0"> <Grid.RenderTransform> <TranslateTransform x:Name="xform" X="-25"/> </Grid.RenderTransform> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="OpenStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="0"/> <VisualTransition GeneratedDuration="0:0:0.2" To="Open"> <Storyboard> <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform"> <DoubleAnimation.EasingFunction> <BackEase Amplitude=".3" EasingMode="EaseOut"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> <DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/> </Storyboard> </VisualTransition> </VisualStateGroup.Transitions> <VisualState x:Name="Closed"> <Storyboard> <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/> </Storyboard> </VisualState> <VisualState x:Name="Open"> <Storyboard> <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform"/> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border CornerRadius="25" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" > <ContentPresenter/> </Border> </Grid> </ControlTemplate> <Style TargetType="local:MyCustomValidationIndicatorControl"> <Style.Triggers> <Trigger Property="IsEditError" Value="False"> <Setter Property="Background" Value="#FFFFE1" /> <Setter Property="BorderBrush" Value="#5D5D5D"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="#5D5D5D"/> </Trigger> <Trigger Property="IsEditError" Value="True"> <Setter Property="Background" Value="LightGreen" /> <Setter Property="BorderBrush" Value="Red"/> <Setter Property="BorderThickness" Value="2"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:MyCustomValidationIndicatorControl"> <Grid x:Name="Root" > <Border x:Name="validationErrorElementBorder" CornerRadius="1" IsHitTestVisible="False"> <ToolTipService.ToolTip> <ToolTip x:Name="ValidationTooltip" Margin="-2,0,0,0" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" IsOpen="{TemplateBinding IsActived}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Template="{StaticResource ValidationToolTipTemplate}"> <StackPanel> <StackPanel.Resources> <Style TargetType="TextBlock"> <Style.Triggers> <Trigger Property="Text" Value=""> <Setter Property="Visibility" Value="Collapsed" /> </Trigger> </Style.Triggers> </Style> </StackPanel.Resources> <TextBlock MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{TemplateBinding Title}" FontWeight="ExtraBold" UseLayoutRounding="false" IsEnabled="False" Foreground="{TemplateBinding Foreground}"/> <TextBlock MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{TemplateBinding Message}" UseLayoutRounding="false" IsEnabled="False" Foreground="{TemplateBinding Foreground}"/> </StackPanel> </ToolTip> </ToolTipService.ToolTip> <Rectangle HorizontalAlignment="Right" VerticalAlignment="Top" Height="8" Width="8"> <Rectangle.Style> <Style TargetType="Rectangle"> <Style.Triggers> <DataTrigger Binding="{Binding IsInvalid}" Value="True"> <Setter Property="Fill" Value="Orange" /> </DataTrigger> <DataTrigger Binding="{Binding IsInvalid}" Value="False"> <Setter Property="Visibility" Value="Hidden" /> </DataTrigger> </Style.Triggers> </Style> </Rectangle.Style> <Rectangle.Clip> <EllipseGeometry Center="4,4" RadiusX="4" RadiusY="4" /> </Rectangle.Clip> </Rectangle> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </gss:GcSpreadSheet.Resources> <gss:GcSpreadSheet.DataValidationTemplate> <DataTemplate DataType="{x:Type gss:DataValidationContext}" > <local:MyCustomValidationIndicatorControl/> </DataTemplate> </gss:GcSpreadSheet.DataValidationTemplate> </gss:GcSpreadSheet> </Grid> |
コードのコピー
|
|
---|---|
// データ検証 IValidation val = GcSpreadSheet.Workbook.ActiveSheet.Cells["B4:B8"].Validation.Add(DataValidationType.List, DataValidationErrorStyle.Stop, DataValidationOperator.Equal, "Valid", ""); val.ShowError = true; val.ShowInput = true; val.ErrorMessage = "エラーメッセージ"; val.ErrorTitle = "タイトルにエラーがあります。"; val.InputMessage = "入力したメッセージです。"; val.InputTitle = "入力したタイトルです。"; // サンプルデータ GcSpreadSheet.Workbook.ActiveSheet.Cells["B4"].Value = "無効"; GcSpreadSheet.Workbook.ActiveSheet.Cells[3, 1].Activate(); GcSpreadSheet.Workbook.ActiveSheet.Cells["B5:B7"].Value = "有効"; GcSpreadSheet.Workbook.ActiveSheet.Cells["B8"].Value = "無効"; GcSpreadSheet.Workbook.ActiveSheet.CircleInvalid(); |
コードのコピー
|
|
---|---|
' データ検証 Dim val As IValidation = GcSpreadSheet.Workbook.ActiveSheet.Cells("B4:B8").Validation.Add(DataValidationType.List, DataValidationErrorStyle.[Stop], DataValidationOperator.Equal, "Valid", "") val.ShowError = True val.ShowInput = True val.ErrorMessage = "エラーメッセージ" val.ErrorTitle = "タイトルにエラーがあります。" val.InputMessage = "入力したメッセージです。" val.InputTitle = "入力したタイトルです。" ' サンプルデータ GcSpreadSheet.Workbook.ActiveSheet.Cells("B4").Value = "無効" GcSpreadSheet.Workbook.ActiveSheet.Cells(3, 1).Activate() GcSpreadSheet.Workbook.ActiveSheet.Cells("B5:B7").Value = "有効" GcSpreadSheet.Workbook.ActiveSheet.Cells("B8").Value = "無効" GcSpreadSheet.Workbook.ActiveSheet.CircleInvalid() |