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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

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

Q&A

解決済

2回答

1040閲覧

DockPanelなどでMessageBoxを表現して標準のMessageBoxのように使いたい

tride

総合スコア68

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

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

1グッド

0クリップ

投稿2019/12/03 08:13

編集2019/12/04 08:00

以下コードはウィンドウ内にパネルを使ってメッセージボックスを表現しています。
この場合に、よくあるMessageBoxのように、ボタン(OKボタンやキャンセルボタンなど)で状況に応じてイベントを起こしたいと思っていますが、どうすればよいか糸口すらつかめず悩んでおります。
通常、MessageBoxの場合、以下C#コードのように戻り値を得る事でその後にif文でボタンの動作を分けると思うのですが、同じような感じにしたいです。

C#

1MessageBoxResult flag = MessageBox.Show("OKですか?");

尚、メッセージボックスの表示非表示は、Layer_MessageBoxWindowをVisibilityをHiddenとVisibleで切替えていることとします。
また、メッセージウィンドウを表示している間は、他の領域に触れない(Layer_MessageBoxWindowがドックパネルで他領域を占有している)状況です。

環境:Visual Studio 2019

<MainWindow.xaml>

xaml

1 <!-- MessageBox Layer --> 2 <DockPanel x:Name="Layer_MessageBoxWindow" Visibility="Hidden" Opacity="0" Background="#50000000"> 3 <StackPanel x:Name="MessageBox" Margin="0" Orientation="Vertical" VerticalAlignment="Center"> 4 <StackPanel Margin="0" Orientation="Horizontal" HorizontalAlignment="Center" > 5 <window:MessageBoxWindow /> 6 </StackPanel> 7 </StackPanel> 8 </DockPanel> 9 10 <!-- Language --> 11 <StackPanel x:Name="Layer_SubWindow" VerticalAlignment="Center"> 12 <window:LanguageMenuWindow x:Name="LanguageMenuWindow" /> 13 </StackPanel>

<MessageBoxWindow.xaml>

xaml

1<UserControl x:Class="AppWPF.UserControlObjects.SubWindow.MessageBoxWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 mc:Ignorable="d" 7 d:DesignHeight="150"> 8 <Grid x:Name="gridMessageBoxWindow" Background="#FFEEEEEE" Width="600" > 9 10 <!-- レイアウト分割 --> 11 <Grid.RowDefinitions> 12 <RowDefinition Height="5"/> 13 <RowDefinition Height="Auto"/> 14 <RowDefinition Height="7*"/> 15 </Grid.RowDefinitions> 16 17 <!-- トップカラーバー --> 18 <Canvas Height="5" Margin="0" Background="#FF0071EF" Grid.Row="0"/> 19 20 <!-- メッセージ部分 --> 21 <StackPanel VerticalAlignment="Center" Margin="25,30,25,25" Grid.Row="1"> 22 <TextBlock x:Name="MessageText" Text="{Binding Path=textData.Text, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Margin="0" FontSize="18" FontWeight="Bold" TextWrapping="Wrap"/> 23 </StackPanel> 24 25 <!-- ボタン部分 --> 26 <StackPanel x:Name="PanelAllButton" Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="2" Margin="0,0,0,10"> 27 <Button x:Name="ButtonOK" Content="OK" VerticalAlignment="Center" Width="90" Height="35" Margin="10,0,10,0" Click="ButtonOK_Click" Visibility="Visible"/> 28 <Button x:Name="ButtonCancel" Content="Cancel" VerticalAlignment="Center" Width="90" Height="35" Margin="10,0,10,0" Click="ButtonCancel_Click"/> 29 </StackPanel> 30 31 </Grid> 32</UserControl>

2019/12/04追記:
回答の際に質問させていただいた内容を追記します。
内容としては別のユーザーコントロールでOKボタンを押し、メッセージウィンドウ(Layer_MessageBoxWindowのDockPanel)をVisibleまたはHiddenで表示切替して、OKボタンを押した結果を以下のような他のユーザーコントロール(LanguageMenuWindow)で受け取りたい場合となります。

尚表示非表示の処理に関しては、本文と違う為省略いたします。
※MainWindow.xamlにも以下xamlを読み込む部分を追記しました。
<LanguageMenuWindow>

Xaml

1<UserControl x:Class="AppWPF.UserControlObjects.SubWindow.LanguageMenuWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 mc:Ignorable="d" Width="108" Height="134"> 7 <Grid x:Name="LanguageMenuPannel" Height="191" VerticalAlignment="Top" Margin="0,0,0,-57"> 8 9 <StackPanel Margin="10,10,10,41"> 10 <RadioButton x:Name="radioButton_ENG" Content="English" Height="22" VerticalContentAlignment="Center" Checked="RadioButtonENG_Checked"/> 11 <RadioButton x:Name="radioButton_JPA" Content="日本語" Height="22" VerticalContentAlignment="Center" Checked="RadioButtonJPA_Checked" /> 12 </StackPanel> 13 <Button x:Name="OK" Content="OK" Margin="10,0,10,10" Height="20" VerticalAlignment="Bottom" Click="OK_Click"/> 14 15 </Grid> 16</UserControl>
TN8001👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

まずMessageBoxWindowはクライアント領域内を完全に覆うのでしょうから単に、

xml

1<Window> 2 <Grid> 3 <window:MessageBoxWindow /> 4 <window:LanguageMenuWindow /> 5 </Grid> 6</Window>

こういう形でいいんじゃないでしょうか。

バインディングをうまく使えば、割とすっきりできそうにも思うのですが、

MessageBoxResult flag = MessageBox.Show("OKですか?");

こういうイメージとのことでちょっと無理やり感もありますが、今のコードをあまり壊さない形でやってみました。


MainWindow

cs

1using System.Diagnostics; 2using System.Windows; 3 4namespace Questions227100 5{ 6 public partial class MainWindow : Window 7 { 8 public MainWindow() => InitializeComponent(); 9 10 private async void Button_Click(object sender, RoutedEventArgs e) 11 { 12 var result = await MessageBoxWindow.ShowAsync(this, "いいんですね?"); 13 14 if(result == MessageBoxResult.OK) Debug.WriteLine("OK"); 15 if(result == MessageBoxResult.Cancel) Debug.WriteLine("Cancel"); 16 } 17 } 18}

xml

1<Window 2 x:Class="Questions227100.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:window="clr-namespace:Questions227100" 6 Width="800" 7 Height="450"> 8 <Grid> 9 <window:MessageBoxWindow x:Name="messageBoxWindow" /> 10 11 <!--<window:LanguageMenuWindow x:Name="LanguageMenuWindow" />--> 12 <!-- ↑の代わりにただのボタン --> 13 <Button Click="Button_Click" Content="何かを実行" /> 14 </Grid> 15</Window>

MessageBoxWindow

cs

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Threading.Tasks; 5using System.Windows; 6using System.Windows.Controls; 7using System.Windows.Media; 8 9namespace Questions227100 10{ 11 public partial class MessageBoxWindow : UserControl 12 { 13 private TaskCompletionSource<MessageBoxResult> taskCompletionSource; 14 15 public MessageBoxWindow() 16 { 17 InitializeComponent(); 18 SetValue(Panel.ZIndexProperty, 10); 19 Visibility = Visibility.Hidden; 20 } 21 22 public static Task<MessageBoxResult> ShowAsync(UIElement element, string message) 23 { 24 var win = Window.GetWindow(element); 25 var msgbox = win.Descendants<MessageBoxWindow>().FirstOrDefault(); 26 if(msgbox == null) throw new InvalidOperationException("MessageBoxWindowが見つかりません。"); 27 return msgbox.ShowAsync(message); 28 } 29 public Task<MessageBoxResult> ShowAsync(string message) 30 { 31 MessageText.Text = message; 32 Visibility = Visibility.Visible; 33 taskCompletionSource = new TaskCompletionSource<MessageBoxResult>(); 34 return taskCompletionSource.Task; 35 } 36 37 private void ButtonOK_Click(object sender, RoutedEventArgs e) 38 { 39 Visibility = Visibility.Hidden; 40 taskCompletionSource.SetResult(MessageBoxResult.OK); 41 } 42 private void ButtonCancel_Click(object sender, RoutedEventArgs e) 43 { 44 Visibility = Visibility.Hidden; 45 taskCompletionSource.SetResult(MessageBoxResult.Cancel); 46 } 47 } 48 49 50 51 //https://blog.xin9le.net/entry/2013/10/29/222336 52 internal static class DependencyObjectExtensions 53 { 54 public static IEnumerable<DependencyObject> Children(this DependencyObject obj) 55 { 56 if(obj == null) throw new ArgumentNullException(nameof(obj)); 57 var count = VisualTreeHelper.GetChildrenCount(obj); 58 if(count == 0) yield break; 59 for(var i = 0; i < count; i++) 60 { 61 var child = VisualTreeHelper.GetChild(obj, i); 62 if(child != null) yield return child; 63 } 64 } 65 public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj) 66 { 67 if(obj == null) throw new ArgumentNullException(nameof(obj)); 68 foreach(var child in obj.Children()) 69 { 70 yield return child; 71 foreach(var grandChild in child.Descendants()) yield return grandChild; 72 } 73 } 74 public static IEnumerable<T> Children<T>(this DependencyObject obj) 75 where T : DependencyObject => obj.Children().OfType<T>(); 76 public static IEnumerable<T> Descendants<T>(this DependencyObject obj) 77 where T : DependencyObject => obj.Descendants().OfType<T>(); 78 } 79}

xml

1<UserControl 2 x:Class="Questions227100.MessageBoxWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 d:DesignHeight="450" 8 d:DesignWidth="800" 9 Background="#4C000000" 10 mc:Ignorable="d"> 11 <Border 12 MaxWidth="500" 13 MaxHeight="300" 14 VerticalAlignment="Center" 15 Background="#FFEEEEEE" 16 BorderBrush="#FF0071EF" 17 BorderThickness="0,5,0,0"> 18 <Grid> 19 <Grid.RowDefinitions> 20 <RowDefinition /> 21 <RowDefinition Height="Auto" /> 22 </Grid.RowDefinitions> 23 <TextBlock 24 x:Name="MessageText" 25 Margin="10" 26 FontWeight="Bold" 27 TextWrapping="Wrap" /> 28 <StackPanel 29 Grid.Row="1" 30 HorizontalAlignment="Right" 31 Orientation="Horizontal"> 32 <Button 33 MinWidth="90" 34 Margin="10" 35 Click="ButtonOK_Click" 36 Content="OK" /> 37 <Button 38 MinWidth="90" 39 Margin="10" 40 Click="ButtonCancel_Click" 41 Content="Cancel" /> 42 </StackPanel> 43 </Grid> 44 </Border> 45</UserControl>

ダイアログだけかっこよくなってもバランスがありますので、
MahApps.Metro - Dialogs
Material Design In XAML Toolkit - Dialogs

こういったものに乗ってしまえば、すでに同様のものが用意されています。
ただ導入するにもまた調整がいるので、是非にとまでは言えません。

投稿2019/12/04 11:15

編集2022/09/15 09:53
TN8001

総合スコア9296

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

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

tride

2019/12/05 08:21

回答ありがとうございます。 現在、環境前にいないので、先にお礼だけしておきます。 ソースについては、後程読んでいきます。 それと既存で公開されているものは、とてもいいですね。 ちょっと試してみたいと思います。
tride

2019/12/09 05:59

> MessageBoxWindowはクライアント領域内を完全に ・・・ 既存のコードから抜き出しての事だったので、このような形で記載してました。 ただ、記載のほうがすっきりしてるので、ちょっとできないか試してみたいと思います。 コードの内容については、理解するのに少々時間を取りましたが、ご記載されてる内容で実現する事ができました。 特にawaitの部分は、コードをみて思わずその手があったかと手をたたきました(笑)
guest

0

WPF はイベント発生元でイベントを処理しなかった場合に、親要素でイベントを処理できます。
これをバブルイベントと言います。
使い方は簡単で、MessageBoxWindowのイベントハンドラを消して、MainWindowのDockPanelにでもイベント処理を書きます。
ButtonBase.Click="Layer_MessageBoxWindow_Click"

そのイベントハンドラprivate void Layer_MessageBoxWindow_Click(object sender, RoutedEventArgs e)
引数 sender に押したボタンコントロールが入ってます。

投稿2019/12/03 08:38

編集2019/12/03 08:40
hihijiji

総合スコア4150

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

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

tride

2019/12/03 10:52

となると、senderにて返ってきたbuttonの名前なりでMainWindow側で条件を判定させてやればよい、という事ですか? もしそうであるなら、他のユーザーコントロールからメッセージボックスのボタン結果を得たい場合も同じようにやればよいという事でしょうか。 少々今目の前に環境がないので、先に回答させて頂きました。
hihijiji

2019/12/06 03:04

あくまでも今のやり方に近い一例を挙げただけですので、このやり方が必ずしもベストではありません。 そのうえでの回答としては、buttonの名前なりで判断せざるを得ないでしょう。 何が良いかは状況に応じて流動的ですから、他のユーザーコントロール云々に対する答えはありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問