🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

2274閲覧

WPF ダイアログボックスのキャンセル方法

kazuoni

総合スコア5

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2020/01/01 15:44

現在、WPFにて、ダイアログボックスを処理する簡単なプログラムを書いております。
下記サイトを参考にしております。

【C#/WPF】EventTriggerを使って、Buttonでなくてもクリック時のCommandをかけるようにする
https://qiita.com/tera1707/items/7ecde6e97a19437cbf72

現在、下記のところまで作成しました。
①メインウィンドウボタンをクリックすると、サブウィンドウがダイアログボックスで立ち上がる
②ダイアログボックスの操作でDialogResultを取得する
③DialogResultの結果をMessageBoxで表示

実現したいことは下記のとおりです。
・サブウィンドウでOKボタンを押した際、TextBox.Text=""ならば、別ダイアログボックスを出力し、入力を促す。
さらに、ボタン操作をキャンセルしたい(サブウィンドウへ再度戻る)

どのように実現すればよいかわからず困っております。
お手数をおかけしますが、ご教授いただけませんでしょうか。

現状のソースコードを下記にアップロードいたしました。
https://15.gigafile.nu/0116-dece8b0fe607e1eb5942bd27c85a0cb0c
DL Key 1192

よろしくお願いいたします。

TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

MVVMにこだわらないのであれば、こんな感じでどうでしょうか。

xml

1<Window 2 x:Class="WpfApp1.SubWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="clr-namespace:WpfApp1" 6 Title="SubWindow" 7 Width="800" 8 Height="450"> 9 <Window.DataContext> 10 <local:SubViewModel /> 11 </Window.DataContext> 12 <Grid> 13 <Grid.RowDefinitions> 14 <RowDefinition /> 15 <RowDefinition /> 16 </Grid.RowDefinitions> 17 <TextBox Text="{Binding Text}" /> 18 <Grid Grid.Row="1"> 19 <Grid.ColumnDefinitions> 20 <ColumnDefinition /> 21 <ColumnDefinition /> 22 </Grid.ColumnDefinitions> 23 <Button Content="Cancel" IsCancel="True" /> 24 <Button 25 Grid.Column="1" 26 Command="{Binding DoSomethingCommand}" 27 CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" 28 Content="OK" 29 IsDefault="True" /> 30 </Grid> 31 </Grid> 32</Window>

cs

1using System.Windows; 2using Prism.Commands; 3 4namespace WpfApp1 5{ 6 public class SubViewModel 7 { 8 public string Text { get; set; } 9 public DelegateCommand<Window> DoSomethingCommand { get; } 10 11 public SubViewModel() 12 { 13 DoSomethingCommand = new DelegateCommand<Window>((w) => 14 { 15 System.Diagnostics.Debug.WriteLine("DoSomethigCommand"); 16 17 if(string.IsNullOrEmpty(Text)) 18 { 19 MessageBox.Show("何か入力してください。"); 20 } 21 else 22 { 23 w.DialogResult = true; 24 } 25 }); 26 } 27 } 28}

実際には入力値はもっとあってそれぞれ検証したいのであれば、INotifyDataErrorInfo等を実装しエラーがあればボタンを押せなくするのがきれいかもしれません。

xml

1<Window 2 x:Class="WpfApp1.SubWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 6 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 7 xmlns:local="clr-namespace:WpfApp1" 8 Name="SubWnd" 9 Title="SubWindow" 10 Width="800" 11 Height="450"> 12 <Window.Resources> 13 <ControlTemplate x:Key="ValidationTemplate"> 14 <StackPanel> 15 <ItemsControl HorizontalAlignment="Right" ItemsSource="{Binding AdornedElement.(Validation.Errors), ElementName=validationTarget}"> 16 <ItemsControl.ItemTemplate> 17 <DataTemplate> 18 <TextBlock Foreground="Red" Text="{Binding ErrorContent}" /> 19 </DataTemplate> 20 </ItemsControl.ItemTemplate> 21 </ItemsControl> 22 <AdornedElementPlaceholder x:Name="validationTarget" /> 23 </StackPanel> 24 </ControlTemplate> 25 </Window.Resources> 26 <Window.DataContext> 27 <local:SubViewModel /> 28 </Window.DataContext> 29 <DockPanel> 30 <StackPanel 31 HorizontalAlignment="Right" 32 DockPanel.Dock="Bottom" 33 Orientation="Horizontal"> 34 <Button 35 MinWidth="80" 36 Margin="5" 37 Command="{Binding DoSomethingCommand}" 38 Content="OK"> 39 <i:Interaction.Triggers> 40 <i:EventTrigger EventName="Click"> 41 <ei:ChangePropertyAction 42 PropertyName="DialogResult" 43 TargetObject="{Binding ElementName=SubWnd}" 44 Value="True" /> 45 </i:EventTrigger> 46 </i:Interaction.Triggers> 47 </Button> 48 <Button 49 MinWidth="80" 50 Margin="5" 51 Content="Cancel" 52 IsCancel="True" /> 53 </StackPanel> 54 55 <StackPanel> 56 <HeaderedContentControl Margin="5" Header="Text1"> 57 <TextBox Text="{Binding Text1, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" /> 58 </HeaderedContentControl> 59 <HeaderedContentControl Margin="5" Header="Text2"> 60 <TextBox Text="{Binding Text2, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" /> 61 </HeaderedContentControl> 62 <HeaderedContentControl Margin="5" Header="Text3"> 63 <TextBox Text="{Binding Text3, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" /> 64 </HeaderedContentControl> 65 </StackPanel> 66 </DockPanel> 67</Window>

cs

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using System.ComponentModel; 5using System.ComponentModel.DataAnnotations; 6using System.Linq; 7using System.Runtime.CompilerServices; 8using Prism.Commands; 9using Prism.Mvvm; 10 11namespace WpfApp1 12{ 13 public class SubViewModel : BindableBase, INotifyDataErrorInfo 14 { 15 [Required(ErrorMessage = "何か入力してください。")] 16 public string Text1 { get => _Text1; set => SetProperty(ref _Text1, value); } 17 private string _Text1; 18 19 [MinLength(10, ErrorMessage = "10文字以上入力してください。")] 20 public string Text2 { get => _Text2; set => SetProperty(ref _Text2, value); } 21 private string _Text2; 22 23 [RegularExpression("[a-z]+", ErrorMessage = "a-zの文字列を入力してください。")] 24 public string Text3 { get => _Text3; set => SetProperty(ref _Text3, value); } 25 private string _Text3; 26 27 public DelegateCommand DoSomethingCommand { get; } 28 29 30 public SubViewModel() 31 { 32 errorsContainer = new ErrorsContainer<string>(x => ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(x))); 33 34 Text1 = ""; // ""に深い意味はない。初期値nullから動かしてValidatorを通してるだけ 35 Text2 = ""; 36 Text3 = "A"; 37 38 DoSomethingCommand = new DelegateCommand( 39 () => System.Diagnostics.Debug.WriteLine("DoSomethigCommand"), 40 () => !HasErrors) 41 .ObservesProperty(() => HasErrors); 42 } 43 44 45 #region INotifyDataErrorInfo 46 private readonly ErrorsContainer<string> errorsContainer; 47 public bool HasErrors => errorsContainer.HasErrors; 48 public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 49 protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) 50 { 51 if(!base.SetProperty(ref storage, value, propertyName)) return false; 52 53 var context = new ValidationContext(this) { MemberName = propertyName }; 54 var errors = new List<ValidationResult>(); 55 if(!Validator.TryValidateProperty(value, context, errors)) 56 { 57 errorsContainer.SetErrors(propertyName, errors.Select(x => x.ErrorMessage)); 58 } 59 else 60 { 61 errorsContainer.ClearErrors(propertyName); 62 } 63 RaisePropertyChanged(nameof(HasErrors)); 64 return true; 65 } 66 public IEnumerable GetErrors(string propertyName) => errorsContainer.GetErrors(propertyName); 67 #endregion 68 } 69}

投稿2020/01/01 23:18

編集2023/07/17 13:20
TN8001

総合スコア9855

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

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

kazuoni

2020/01/02 12:04

非常に的確なご回答ありがとうございます。 実現したかったことすべてが詰まっております。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問