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

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

新規登録して質問してみよう
ただいま回答率
85.48%
blazor

Blazorは、マイクロソフトが開発している.NETベースのWebアプリフレームワークです。C#でフロントエンドもバックエンドも一貫して書くことが可能。クライアントサイド(WebAssembly)とサーバーサイド形式のホスティングモデルがあります。

C#

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

Q&A

解決済

3回答

1920閲覧

Blazorでフォームの再検証を行うには?

sgty24

総合スコア8

blazor

Blazorは、マイクロソフトが開発している.NETベースのWebアプリフレームワークです。C#でフロントエンドもバックエンドも一貫して書くことが可能。クライアントサイド(WebAssembly)とサーバーサイド形式のホスティングモデルがあります。

C#

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

0グッド

0クリップ

投稿2023/02/06 05:16

編集2023/02/07 04:49

したいこと

  • カスタム検証(融点(Melting point)<=沸点(Boiling point))を定義したクラスがあり、この入力フォームを作成しています。
  • このクラスの入力フォームを作ったときMelting point入力→Boiling pointとするとMelting pointの検証エラーが消えません。
  • Boiling point入力時にMelting pointの再検証を行うにはどうすればよいでしょうか?
  • ASP.NET MVCだと「TryValidateModel」というのがあるようなのですが、BlazorのRazorコンポーネントでは@modelは使えそうにありません。
  • 参考URL:ASP.NET Core MVC および Razor Pages でのモデルの検証 - 検証を再実行する
  • MudBlazorを利用した状態でのコードが知りたいところではありますが、標準のEditFormならこうする、という情報でも頂けるとありがたいです。

開発環境

  • Visual Studio 2022
  • .NET 6.0 (※LTSなので使っているだけなので、7.0ならこう解決できる、というのがあれば教えて欲しいと思っています)
  • Blazor Server
  • 利用コンポーネント ライブラリ:MudBlazor

ソースコード

C#

1 public class Element 2 { 3 [Required(ErrorMessage = "Name is required")] 4 public string Name { get; set; } = ""; 5 6 [Required(ErrorMessage = "Melting point is required")] 7 [CheckMeltByBoil(ErrorMessage = "Boiling point must be higher than melting point.")] 8 public double MeltingPoint { get; set; } = 0.0; 9 10 [Required(ErrorMessage = "Boiling point is required")] 11 [CheckBoilByMelt(ErrorMessage = "Boiling point must be higher than melting point.")] 12 public double BoilingPoint { get; set; } = 0.0; 13 } 14 //サンプル:new Element { Name = "Hydrogen", MeltingPoint = -259.14, BoilingPoint = -252.87 }, 15 16 [AttributeUsage(AttributeTargets.Property)] 17 public class CheckMeltByBoilAttribute : ValidationAttribute 18 { 19 protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) 20 { 21 var model = validationContext.ObjectInstance as Element; 22 if (model is null || value is null) 23 { 24 throw new NullReferenceException(); 25 } 26 27 if ((double)value <= model.BoilingPoint) 28 { 29 return ValidationResult.Success; 30 } 31 else 32 { 33 return new ValidationResult(null); 34 } 35 } 36 } 37 38 [AttributeUsage(AttributeTargets.Property)] 39 public class CheckBoilByMeltAttribute : ValidationAttribute 40 { 41 protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) 42 { 43 var model = validationContext.ObjectInstance as Element; 44 if (model is null || value is null) 45 { 46 throw new NullReferenceException(); 47 } 48 49 if (model.MeltingPoint <= (double)value) 50 { 51 return ValidationResult.Success; 52 } 53 else 54 { 55 return new ValidationResult(null); 56 } 57 } 58 }

Razor

1@using System.Globalization 2@using MudDataGridSample.Data 3 4<MudDialog> 5 <TitleContent> 6 <MudText Typo="Typo.h6"> 7 @(IsEdit ? "Edit" : "Create") 8 </MudText> 9 </TitleContent> 10 <DialogContent> 11 <MudForm @ref="form" @bind-IsValid="@success"> 12 <MudStack Spacing="1"> 13 <MudTextField Label="Name" HelperText="(HelperText)" @bind-Value="EditData.Name" For="@(() => EditData.Name)" /> 14 <MudNumericField Label="MeltingPoint" HelperText="(HelperText)" Format="N4" Culture="@CultureInfo.GetCultureInfo("en-US")" T="double" @bind-Value="EditData.MeltingPoint" For="@(() => EditData.MeltingPoint)" TextChanged="(string _val) => OnValueChangeHandler1(_val)" /> 15 <MudNumericField Label="BoilingPoint" HelperText="(HelperText)" Format="N4" Culture="@CultureInfo.GetCultureInfo("en-US")" T="double" @bind-Value="EditData.BoilingPoint" For="@(() => EditData.BoilingPoint)" TextChanged="(string _val) => OnValueChangeHandler2(_val)" /> 16 </MudStack> 17 </MudForm> 18 </DialogContent> 19 <DialogActions> 20 <MudButton OnClick="Cancel">Cancel</MudButton> 21 <MudButton Color="Color.Primary" Disabled="@(!success)" OnClick="Submit">Ok</MudButton> 22 </DialogActions> 23</MudDialog> 24 25@code { 26 bool success = false; 27 MudForm? form; 28 29 [CascadingParameter] MudDialogInstance? MudDialog { get; set; } 30 31 [Parameter] public bool IsEdit { get; set; } = false; 32 [Parameter] public Element EditData { get; set; } = new(); 33 34 35 protected async Task OnValueChangeHandler1(string newValue) 36 { 37 double set_val = 0.0; 38 if (!double.TryParse(newValue, out set_val)) 39 { 40 return; 41 } 42 43 //入れ直してStateHasChangedしても効果無し 44 EditData.MeltingPoint = set_val; 45 double tmp = EditData.BoilingPoint; 46 EditData.BoilingPoint = EditData.BoilingPoint + 1.0; 47 await InvokeAsync(StateHasChanged); 48 EditData.BoilingPoint = tmp; 49 await InvokeAsync(StateHasChanged); 50 } 51 52 protected async Task OnValueChangeHandler2(string newValue) 53 { 54 double set_val = 0.0; 55 if (!double.TryParse(newValue, out set_val)) 56 { 57 return; 58 } 59 60 //入れ直してStateHasChangedしても効果無し 61 EditData.BoilingPoint = set_val; 62 double tmp = EditData.MeltingPoint; 63 EditData.MeltingPoint = EditData.MeltingPoint + 1.0; 64 await InvokeAsync(StateHasChanged); 65 EditData.MeltingPoint = tmp; 66 await InvokeAsync(StateHasChanged); 67 } 68 69 void Submit() => MudDialog?.Close(DialogResult.Ok(true)); 70 void Cancel() => MudDialog?.Cancel(); 71}

MudBlazorを使わずEditFormを使うなら以下のようになるでしょうか?
この場合はフォーカス移動だけで無く、値を入れ直さないとバリデーションチェックが走りませんでした。
操作例:
1.Melting pointに1を設定してフォーカスをBoiling pointに移動
→Melting pointのバリデーションメッセージ表示
2.Boiling pointに-255を設定してフォーカスをMelting pointに移動
→Boiling pointのバリデーションメッセージ表示
3.Melting pointに-999を設定してフォーカスをBoiling pointに移動
→Melting pointのバリデーションメッセージ表示が消えるがBoiling pointのバリデーションメッセージはそのまま。
4.Boiling pointの値を変えずにSaveボタンにフォーカスを移動
→変化無し
5.Boiling pointに-255を設定してSaveボタンにフォーカスを移動
→Boiling pointのバリデーションメッセージ表示が消える。

Razor

1@using System.Globalization 2@using MudDataGridSample.Data 3 4<EditForm Model="@EditData" @ref="form" OnValidSubmit="@Submit"> 5 <DataAnnotationsValidator /> 6 <div> 7 <label>Name</label> 8 <InputText @bind-Value="EditData.Name"></InputText> 9 &nbsp;<ValidationMessage For="@(() => EditData.Name)" /> 10 </div> 11 <br /> 12 <div> 13 <label>Melting point</label> 14 <InputNumber TValue="Double" @bind-Value="EditData.MeltingPoint" /> 15 &nbsp;<ValidationMessage For="@(() => EditData.MeltingPoint)" /> 16 </div> 17 <br /> 18 <div > 19 <label >Boiling point</label> 20 <InputNumber TValue="Double" @bind-Value="EditData.BoilingPoint" /> 21 &nbsp;<ValidationMessage For="@(() => EditData.BoilingPoint)" /> 22 </div> 23 <br /> 24 <div > 25 <input type="submit" value="Save" /> 26 </div> 27</EditForm> 28 29@code { 30 EditForm? form; 31 32 public Element EditData { get; set; } = new Element { Name = "Hydrogen", MeltingPoint = -259.14, BoilingPoint = -252.87 }; 33 34 private async Task Submit() 35 { 36 37 await InvokeAsync(StateHasChanged); 38 } 39}

試したこと

  • TextChangedイベントで値を入れ直してStateHasChangedを呼んでも効果はありませんでした。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/02/06 05:26

質問するならちゃんと開発環境を書きましょう。Blazor Server なのか WASM なのかさえも書いてない。
sgty24

2023/02/06 05:34

失礼しました。追記しました。
退会済みユーザー

退会済みユーザー

2023/02/06 22:55

MudBlazor 抜きで、単に 2 つのユーザー入力の検証の話にできないですか?
sgty24

2023/02/07 04:50

EditFormに関する記述を追加しました。 MudBlazorを利用した状態でのコードが知りたいところではありますが、標準のEditFormならこうする、という情報でも頂けるとありがたいです。
退会済みユーザー

退会済みユーザー

2023/02/07 06:28

プロパティにまたがるユーザー入力の検証がしたいのではなかろうかと想像してますが、ASP.NET MVC であればその目的には CustomValidation 属性というのがあります。Blazor Server にもそれが使えないかとちょっと思ったので上のコメントで「MudBlazor 抜きで、単に 2 つのユーザー入力の検証の話にできないですか?」と聞きました。 CustomValidation 属性 http://surferonwww.info/BlogEngine/post/2020/02/25/custom-validation-attribute.aspx 思い付きレベルの話で検証などは全くしてませんのでハズレだったらすみません。
sgty24

2023/02/07 09:44

丁寧にありがとうございますm(_ _)m 現状のコードはCustomValidation属性ではなくValidationAttributeを継承した  ・CheckMeltByBoilAttribute  ・CheckBoilByMeltAttribute を定義してMeltPointとBoilPointに属性として当てることで「2つの値にまたがるユーザー入力の検証」自体はできています。 参考:[C#]ValidationAttributeを継承して2つの項目の大小関係を検証する https://qiita.com/nr_ck/items/b83f4d4373f132e0476e ただ、  ・Melt point(融点)を入力してエラーになった際にBoil point(沸点)のエラーも表示させたい  ・Boil point(沸点)を入力してエラーになった際にMelt point(融点)のエラーも表示させたい  ・Melt point(融点)を入力したエラーが解消した際にBoil point(沸点)のエラーも解消させたい  ・Boil point(沸点)を入力したエラーが解消した際にMelt point(融点)のエラーも解消させたい というUI上の挙動が実現できていないという状況です。 一応自己解決で書いた通り、MudBlazorであれば form?.Validate(); を呼ぶことで バリデーションが再度実行されて上記仕様を満たすことができるのですが、 この場合Nameのバリデーションも実行されてしまうため、入力する人が  「必要なのは分かってる。後から入れようと思ってたのにうるさいなぁ」 とUXを若干害することが懸念されたのでもうすこし何とかならないかなぁと思っている次第です。
退会済みユーザー

退会済みユーザー

2023/02/07 11:31

> ・Melt point(融点)を入力してエラーになった際にBoil point(沸点)のエラーも表示させたい > ・Boil point(沸点)を入力してエラーになった際にMelt point(融点)のエラーも表示させたい > ・Melt point(融点)を入力したエラーが解消した際にBoil point(沸点)のエラーも解消させたい > ・Boil point(沸点)を入力したエラーが解消した際にMelt point(融点)のエラーも解消させたい BoilingPoint にのみ検証属性を付与して、検証結果 NG (MeltingPoint > BoilingPoint) なら "MeltingPoint < BoilingPoint に設定してください" というようなエラーメッセージを BoilingPoint 入力の下に表示するというのではダメなのですか? 以下の記事のように。 ASP.NET MVC 用の CompareValidator http://surferonwww.info/BlogEngine/post/2018/12/31/compare-validator-for-aspnet-mvc.aspx そうすれば上の 4 つの件は悩まなくて済みそうな気がしますけど。 > この場合Nameのバリデーションも実行されてしまうため、 RequiredAttribute による検証はクライアント側とサーバー側の両方で行われませんか? ASP.NET MVC はそうなります。Blazor Server は分かりませんが。 一方、CheckMeltByBoilAttribute, CheckBoilByMeltAttribute による検証はサーバー側でないと行われないはずです。(MudBlazor ではクライアント側でも検証される? ちょっと考えにくいのですが) そして、RequiredAttribute によるクライアント側の検証で検証結果 NG となった場合はサーバーへの送信はキャンセルされる、なので CheckMeltByBoilAttribute, CheckBoilByMeltAttribute による検証は動かないということになるのでは?
退会済みユーザー

退会済みユーザー

2023/02/07 22:17

自分でもちょっと試してみました。上のコメントの後半の方の、 > RequiredAttribute による検証はクライアント側とサーバー側の両方で行われませんか? ASP.NET MVC はそうなります。Blazor Server は分かりませんが。 はまるっきりハズレでした。忘れてください。 前半の方の、 > BoilingPoint にのみ検証属性を付与して・・・ は原因不明で期待通り動かないケースがありました。もう少し考えてみますがなんとなくダメっぽい気がしてます。何か分かったら連絡します。
退会済みユーザー

退会済みユーザー

2023/02/08 22:29

質問者さん、回答したのでそれに対するフィードバック (役に立った/立たなかった。役に立たなかったならどこがダメだったかなど) を返してください。
sgty24

2023/02/09 05:04

了解しました。しっかり見れていないので月曜ぐらいには回答させて頂きたいと思います。
退会済みユーザー

退会済みユーザー

2023/02/15 01:23

今日は水曜日ですけど? 回答してもらわなくていいので、いつまでもスレッドをオープンしておかないでクロースしてください。
sgty24

2023/02/16 01:37

すみません、遅くなりました。 ひとまず自己解決とさせて頂きました。
guest

回答3

0

【オマケ追記】

本題とは違う話ですが・・・

質問のコードのように InputNumber を使うと、

<InputNumber TValue="Double" @bind-Value="EditData.MeltingPoint" />

検証にいろいろ問題がでるようです。具体的には:

(1) テキストボックス入力を空白にした場合、モデルのプロパティに、

[Required(ErrorMessage = "Melting point は必須入力")]

を設定しても無視されて、以下のようなエラーメッセージとなってしまう。

イメージ説明

(2) レンダリングされる html の input 要素の type 属性が "number" となり、入力の制約がブラウザ依存となる。Edge, Chrome, Opera では数字と + - . 以外の文字は受け付けなくなる。Firefox では何でも入力できてしまう。

(3) プロパティに RegularExpression 属性を追加してもやはり無視される。

ASP.NET MVC での検証にも同様な問題があります。上の問題を解決するには InputNumber に代えて InputText を使用し、Required 属性と RegularExpression 属性で検証を行うことです。

具体例を以下に載せておきます。

MyValidation.razor

質問のコードの InputNumber を InputText に変更。

RAZOR

1@using BlazorServer.Models; 2 3@page "/myvalidation" 4 5<PageTitle>My Validation</PageTitle> 6 7<h3>My Validation</h3> 8 9<EditForm Model="@EditData" @ref="form" OnValidSubmit="@Submit"> 10 <DataAnnotationsValidator /> 11 <ValidationSummary></ValidationSummary> 12 <div> 13 <label>Name</label> 14 <InputText @bind-Value="EditData.Name"></InputText> 15 &nbsp;<ValidationMessage For="@(() => EditData.Name)" /> 16 </div> 17 <br /> 18 <div> 19 <label>Melting point</label> 20 <InputText @bind-Value="EditData.MeltingPoint" /> 21 &nbsp;<ValidationMessage For="@(() => EditData.MeltingPoint)" /> 22 </div> 23 <br /> 24 <div > 25 <label >Boiling point</label> 26 <InputText @bind-Value="EditData.BoilingPoint" /> 27 &nbsp;<ValidationMessage For="@(() => EditData.BoilingPoint)" /> 28 </div> 29 <br /> 30 <div > 31 <input type="submit" value="Save" /> 32 </div> 33</EditForm> 34 35@code { 36 EditForm? form; 37 38 public CustomValidationModel3 EditData { get; set; } = new CustomValidationModel3(); 39 40 private async Task Submit() 41 { 42 await InvokeAsync(StateHasChanged); 43 } 44}

Model と Validator

C#

1using System.ComponentModel.DataAnnotations; 2using System.Globalization; 3using System.Reflection; 4 5namespace BlazorServer.Models 6{ 7 [CustomValidation(typeof(CustomValidationModel3), "ValidateTemp")] 8 public class CustomValidationModel3 9 { 10 [Required(ErrorMessage = "Name は必須入力")] 11 public string Name { get; set; } = ""; 12 13 [Required(ErrorMessage = "Melting point は必須入力")] 14 [RegularExpression(@"^[+-]?\d*\.?\d*$", 15 ErrorMessage = "実数(例: +1.23) 形式。符号と小数点は省略可")] 16 public string MeltingPoint { get; set; } = ""; 17 18 [Required(ErrorMessage = "Boiling point は必須入力")] 19 [RegularExpression(@"^[+-]?\d*\.?\d*$", 20 ErrorMessage = "実数(例: +1.23) 形式。符号と小数点は省略可")] 21 public string BoilingPoint { get; set; } = ""; 22 23 public static ValidationResult ValidateTemp(CustomValidationModel3 model, ValidationContext context) 24 { 25 if (model == null) 26 { 27 throw new NullReferenceException(); 28 } 29 30 if (double.Parse(model.MeltingPoint) >= double.Parse(model.BoilingPoint)) 31 { 32 return new ValidationResult("MeltingPoint < BoilingPoint でなければなりません"); 33 } 34 else 35 { 36 return ValidationResult.Success!; 37 } 38 } 39 } 40}

結果は以下の通り。

イメージ説明

投稿2023/02/09 02:56

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

sgty24

2023/02/16 01:36

回答ありがとうございます。 私はMudBlazorを使って検証を進めたんですが、検証をつけるクラス定義のプロパティをNullableにしたら動作するようになりました。 状況に応じて使い分けたいと思います。
guest

0

質問のコメントに書いた、

・Melt point(融点)を入力してエラーになった際にBoil point(沸点)のエラーも表示させたい
・Boil point(沸点)を入力してエラーになった際にMelt point(融点)のエラーも表示させたい
・Melt point(融点)を入力したエラーが解消した際にBoil point(沸点)のエラーも解消させたい
・Boil point(沸点)を入力したエラーが解消した際にMelt point(融点)のエラーも解消させたい

BoilingPoint にのみ検証属性を付与して、検証結果 NG (MeltingPoint > BoilingPoint) なら "MeltingPoint < BoilingPoint に設定してください" というようなエラーメッセージを BoilingPoint 入力の下に表示するというのではダメなのですか? 以下の記事のように。

ASP.NET MVC 用の CompareValidator
http://surferonwww.info/BlogEngine/post/2018/12/31/compare-validator-for-aspnet-mvc.aspx

は、やってみましたが、検証されるもののエラーメッセージが表示されないケースがあるなどの問題があってダメでした。Blazor Server で検証がかかる条件・タイミングが不明で、それを調べて対処する気力が無いので断念。

その前に、CustomValidation 属性を使う提案をしましたが、

CustomValidation 属性
http://surferonwww.info/BlogEngine/post/2020/02/25/custom-validation-attribute.aspx

その中の「モデルレベル」で検証を行って、エラーメッセージは ValidationSummary に表示するという方法ですと、上の 4 つの件は解決できそうです。

ちなみに「プロパティレベル」では、検証されるもののエラーメッセージが表示されないケースがあるなどの同様な問題でダメでした。

以下に検証に使ったコードを書いておきます。

MyValidation.razor

質問のコードほぼそのまま。

RAZOR

1@using BlazorServer.Models; 2 3@page "/myvalidation" 4 5<PageTitle>My Validation</PageTitle> 6 7<h3>My Validation</h3> 8 9<EditForm Model="@EditData" @ref="form" OnValidSubmit="@Submit"> 10 <DataAnnotationsValidator /> 11 <ValidationSummary></ValidationSummary> 12 <div> 13 <label>Name</label> 14 <InputText @bind-Value="EditData.Name"></InputText> 15 &nbsp;<ValidationMessage For="@(() => EditData.Name)" /> 16 </div> 17 <br /> 18 <div> 19 <label>Melting point</label> 20 <InputNumber TValue="Double" @bind-Value="EditData.MeltingPoint" /> 21 &nbsp;<ValidationMessage For="@(() => EditData.MeltingPoint)" /> 22 </div> 23 <br /> 24 <div > 25 <label >Boiling point</label> 26 <InputNumber TValue="Double" @bind-Value="EditData.BoilingPoint" /> 27 &nbsp;<ValidationMessage For="@(() => EditData.BoilingPoint)" /> 28 </div> 29 <br /> 30 <div > 31 <input type="submit" value="Save" /> 32 </div> 33</EditForm> 34 35@code { 36 EditForm? form; 37 38 //public Element EditData { get; set; } = new Element(); 39 //public CustomValidationModel EditData { get; set; } = new CustomValidationModel(); 40 public CustomValidationModel2 EditData { get; set; } = new CustomValidationModel2(); 41 42 private async Task Submit() 43 { 44 await InvokeAsync(StateHasChanged); 45 } 46}

Model と Validator

一番最後の CustomValidationModel2 を使います。その上はやってみたダメだったものですが、参考までに載せておきます。

C#

1using System.ComponentModel.DataAnnotations; 2using System.Globalization; 3using System.Reflection; 4 5namespace BlazorServer.Models 6{ 7 public class Element 8 { 9 [Required(ErrorMessage = "Name は必須入力")] 10 public string Name { get; set; } = ""; 11 12 [Required(ErrorMessage = "Melting point は必須入力")] 13 //[CheckMeltByBoil(ErrorMessage = "Boiling point must be higher than melting point.")] 14 public double MeltingPoint { get; set; } = 0.0; 15 16 [Required(ErrorMessage = "Boiling point は必須入力")] 17 //[CheckBoilByMelt(ErrorMessage = "Boiling point must be higher than melting point.")] 18 [TempHigherThan("MeltingPoint", "{0} は MeltingPoint より高い温度に設定してください")] 19 public double BoilingPoint { get; set; } = 0.0; 20 } 21 22 [AttributeUsage(AttributeTargets.Property)] 23 public class TempHigherThanAttribute : ValidationAttribute 24 { 25 private string _lowerTempPropertyName; 26 27 // コンストラクタ 28 public TempHigherThanAttribute(string lowerTempPropertyName, string errorMsg) 29 { 30 this._lowerTempPropertyName = lowerTempPropertyName; 31 this.ErrorMessage = errorMsg; 32 } 33 34 public override string FormatErrorMessage(string name) 35 { 36 return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name); 37 } 38 39 protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) 40 { 41 if (value == null) 42 { 43 return new ValidationResult("プロパティの値が null"); 44 } 45 46 PropertyInfo? propertyInfo = validationContext.ObjectType.GetProperty(this._lowerTempPropertyName); 47 if (propertyInfo == null) 48 { 49 return new ValidationResult("比較対象の PropertyInfo が null"); 50 } 51 52 object? propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null); 53 if (propertyValue == null) 54 { 55 return new ValidationResult("比較対象の PropertyValue が null"); 56 } 57 58 if ((double)value! > (double)propertyValue) 59 { 60 return ValidationResult.Success; 61 } 62 else 63 { 64 // ValidationResult の引数に null または "" を設定する 65 // と FormatErrorMessage メソッドの戻り値が設定される 66 return new ValidationResult(null); 67 } 68 } 69 } 70 71 public class CustomValidationModel 72 { 73 [Required(ErrorMessage = "Name は必須入力")] 74 public string Name { get; set; } = ""; 75 76 [Required(ErrorMessage = "Melting point は必須入力")] 77 //[CustomValidation(typeof(CustomValidationModel), "ValidateTemp")] 78 public double MeltingPoint { get; set; } = 0.0; 79 80 [Required(ErrorMessage = "Boiling point は必須入力")] 81 [CustomValidation(typeof(CustomValidationModel), "ValidateTemp")] 82 public double BoilingPoint { get; set; } = 0.0; 83 84 public static ValidationResult ValidateTemp(double higherTemp, ValidationContext context) 85 { 86 var model = context.ObjectInstance as CustomValidationModel; 87 if (model == null) 88 { 89 throw new NullReferenceException(); 90 } 91 92 if (model.MeltingPoint >= model.BoilingPoint) 93 { 94 return new ValidationResult("MeltingPoint < BoilingPoint でなければなりません"); 95 } 96 else 97 { 98 return ValidationResult.Success!; 99 } 100 } 101 } 102 103 104 [CustomValidation(typeof(CustomValidationModel2), "ValidateTemp")] 105 public class CustomValidationModel2 106 { 107 [Required(ErrorMessage = "Name は必須入力")] 108 public string Name { get; set; } = ""; 109 110 [Required(ErrorMessage = "Melting point は必須入力")] 111 public double MeltingPoint { get; set; } = 0.0; 112 113 [Required(ErrorMessage = "Boiling point は必須入力")] 114 public double BoilingPoint { get; set; } = 0.0; 115 116 public static ValidationResult ValidateTemp(CustomValidationModel2 model, ValidationContext context) 117 { 118 if (model == null) 119 { 120 throw new NullReferenceException(); 121 } 122 123 if (model.MeltingPoint >= model.BoilingPoint) 124 { 125 return new ValidationResult("MeltingPoint < BoilingPoint でなければなりません"); 126 } 127 else 128 { 129 return ValidationResult.Success!; 130 } 131 } 132 } 133}

結果は以下の通りです。上の CustomValidationModel2 クラスの ValidateTemp メソッドは[Save]ボタンがクリックされたときのみ働きます。

イメージ説明

投稿2023/02/08 02:49

編集2023/02/08 22:35
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

sgty24

2023/02/16 01:31

コメントが遅くなってすみません。 実現したかったUIは入力に併せて動的にバリデーションがかかるものなので、欲しかったものとは異なるのですがこれはこれで参考になりました。ありがとうございます。
guest

0

自己解決

少し自己解決

TextChangeイベントで値を入れてform?.Validate();を呼ぶようにしたら一応できました。
Nameのバリデーションまで動いてしまうのが玉に瑕ですが(´・ω・`)

Razor

1@using System.Globalization 2@using MudDataGridSample.Data 3 4<MudDialog> 5 <TitleContent> 6 <MudText Typo="Typo.h6"> 7 @(IsEdit ? "Edit" : "Create") 8 </MudText> 9 </TitleContent> 10 <DialogContent> 11 <MudForm @ref="form" @bind-IsValid="@success"> 12 <MudStack Spacing="1"> 13 <MudTextField Label="Name" HelperText="(HelperText)" @bind-Value="EditData.Name" For="@(() => EditData.Name)" /> 14 <MudNumericField Label="MeltingPoint" 15 HelperText="(HelperText)" 16 Format="N4" 17 Culture="@CultureInfo.GetCultureInfo("en-US")" 18 T="double" 19 @bind-Value="EditData.MeltingPoint" 20 For="@(() => EditData.MeltingPoint)" 21 TextChanged="(string _val) => OnValueChangeHandler1(_val)" /> 22 <MudNumericField Label="BoilingPoint" 23 HelperText="(HelperText)" 24 Format="N4" 25 Culture="@CultureInfo.GetCultureInfo("en-US")" 26 T="double" 27 @bind-Value="EditData.BoilingPoint" 28 For="@(() => EditData.BoilingPoint)" 29 TextChanged="(string _val) => OnValueChangeHandler2(_val)" /> 30 </MudStack> 31 </MudForm> 32 </DialogContent> 33 <DialogActions> 34 <MudButton OnClick="Cancel">Cancel</MudButton> 35 <MudButton Color="Color.Primary" Disabled="@(!success)" OnClick="Submit">Ok</MudButton> 36 </DialogActions> 37</MudDialog> 38 39@code { 40 bool success = false; 41 MudForm? form; 42 43 [CascadingParameter] MudDialogInstance? MudDialog { get; set; } 44 45 [Parameter] public bool IsEdit { get; set; } = false; 46 [Parameter] public Element EditData { get; set; } = new(); 47 48 protected async Task OnValueChangeHandler1(string newValue) 49 { 50 await Task.Delay(0); 51 double set_val = 0.0; 52 if (!double.TryParse(newValue, out set_val)) 53 { 54 return; 55 } 56 57 EditData.MeltingPoint = set_val; 58 form?.Validate(); 59 } 60 61 protected async Task OnValueChangeHandler2(string newValue) 62 { 63 await Task.Delay(0); 64 double set_val = 0.0; 65 if (!double.TryParse(newValue, out set_val)) 66 { 67 return; 68 } 69 EditData.BoilingPoint = set_val; 70 form?.Validate(); 71 } 72 73 void Submit() => MudDialog?.Close(DialogResult.Ok(true)); 74 void Cancel() => MudDialog?.Cancel(); 75}

投稿2023/02/06 08:51

sgty24

総合スコア8

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問