33章:WPF計算クイズの作成

    作成2013.04.24

     ここでは、Windowsフォームアプリケーション用サンプルコードをWPFアプリケーション用コードに変換します。フォームアプリケーションからWPFアプリケーションへの変化が最近の主流のようです。

  1. 参照元情報
    「WPF計算クイズの作成」にジャンプする
    「10 行でズバリ!! [C#] WPF - Windows フォーム用のコントロールを使う」にジャンプする
     作成方法の詳細は上記を参照願います。


  2. フォームアプリケーションからWPFアプリケーションへの変更
     若干の変更でフォームアプリケーションからWPFアプリケーションへの変更ができます。
     完成ファイルは以下からダウンロードできます。
     ダウンロード後は解凍してから使用してください。
      [WPF計算クイズの作成]をダウンロードする。
     解凍すると「33WpfMathQuiz」フォルダーがあります。
    注(1)「33WpfMathQuiz」フォルダーの「WpfMathQuiz.sln」ファイルをダブルクリックすると「Express 2012 for Windows Desktop」が起動します。
    注(2)メニューの「ウインド」_「ウインドレイアウトのリセット」で標準に戻ります。
    注(3)「ソリューションエクスプローラ」ウインドウ内の「MainWindow.xaml」をダブルクリックすると「デザイン」と「XAML」が表示されます。
    注(4)メニューの「表示」_「コード」を選択するとコードが表示されます。
    注(5)「WpfMathQuiz.sln」の動作確認は「デバッグ」_「デバッグ開始」で実行します。デバッグ機能を用いて動作確認を行います。


  3. WpfMathQuiz.slnの実行
    (1)「Express 2012 for Windows Desktop」のデバッグ機能を使用します。
    (2)「デバッグ」_「デバッグ開始」を選択します。
    (3)クイズスタート前の画面が表示されます。
    (4)Start the quizボタンを押すと問題と残り時間が表示されます。
    (5)+解答欄にカーソルを移し、値をキーボード入力して、リターンします。
    (6)次に-、×、÷の順で解答します。
    (7)制限時間内の全問正解すれば成功です。
    (8)クローズボックスでプログラムを終了します。


  4. プロジェクトの構成
    (1)UserControl1.vbの構成
    ・Timer1を配置します。

    (2)XAMLコードの構成
    ・UserControl1を配置します。
    ・LabelとTextBoxとButtonを配置します。

    注:Timer1がフォームアプリケーション用のツールとなります。


  5. MainWindow.xamlの全コード
    <Window x:Class="WpfMathQuiz.MainWindow"	
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"	
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"	
                xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 	
        xmlns:self="clr-namespace:WpfMathQuiz"	
        Title="MainWindow" Height="350" Width="525">	
        <Grid >	
            <Grid.RowDefinitions>	
                <RowDefinition Height="*" />	
                <RowDefinition Height="*" />	
                <RowDefinition Height="*" />	
                <RowDefinition Height="*" />	
                <RowDefinition Height="*" />	
                <RowDefinition Height="*" />	
    	
            </Grid.RowDefinitions>	
            <Grid.ColumnDefinitions>	
                <ColumnDefinition Width="*" />	
                <ColumnDefinition Width="*" />	
                <ColumnDefinition Width="*" />	
                <ColumnDefinition Width="*" />	
                <ColumnDefinition Width="*" />	
            </Grid.ColumnDefinitions>	
    	
            <Label Content="Time Left" Grid.Column="2"  HorizontalAlignment="Center" Name="Label1" VerticalAlignment="Center" />	
            <Label Content="" HorizontalAlignment="Center"  Name="timeLabel" VerticalAlignment="Center" Grid.Column="3" Grid.ColumnSpan="2" MinWidth="150" />	
            <Label Content="?" HorizontalAlignment="Center" Name="plusLeftLabel" VerticalAlignment="Center" Grid.Row="1" />	
            <Label Content="+" HorizontalAlignment="Center" Name="Label4" VerticalAlignment="Center" Grid.Column="1" Grid.Row="1" />	
            <Label Content="?" HorizontalAlignment="Center" Name="plusRightLabel" VerticalAlignment="Center" Grid.Column="2" Grid.Row="1" />	
            <Label Content="=" HorizontalAlignment="Center" Name="Label6" VerticalAlignment="Center" Grid.Column="3" Grid.Row="1" />	
            <Label Content="?" HorizontalAlignment="Center" Name="minusLeftLabel" VerticalAlignment="Center" Grid.Row="2" />	
            <Label Content="-" HorizontalAlignment="Center" Name="Label8" VerticalAlignment="Center" Grid.Column="1" Grid.Row="2" />	
            <Label Content="?" HorizontalAlignment="Center" Name="minusRightLabel" VerticalAlignment="Center" Grid.Column="2" Grid.Row="2" />	
            <Label Content="=" HorizontalAlignment="Center" Name="Label10" VerticalAlignment="Center" Grid.Column="3" Grid.Row="2" />	
            <Label Content="?" HorizontalAlignment="Center" Name="timesLeftLabel" VerticalAlignment="Center" Grid.Row="3" />	
            <Label Content="×" HorizontalAlignment="Center" Name="Label12" VerticalAlignment="Center" Grid.Column="1" Grid.Row="3" />	
            <Label Content="?" HorizontalAlignment="Center" Name="timesRightLabel" VerticalAlignment="Center" Grid.Column="2" Grid.Row="3" />	
            <Label Content="=" HorizontalAlignment="Center" Name="Label14" VerticalAlignment="Center" Grid.Column="3" Grid.Row="3" />	
            <Label Content="?" HorizontalAlignment="Center" Name="dividedLeftLabel" VerticalAlignment="Center" Grid.Row="4" />	
            <Label Content="÷" HorizontalAlignment="Center" Name="Label16" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4" />	
            <Label Content="?" HorizontalAlignment="Center" Name="dividedRightLabel" VerticalAlignment="Center" Grid.Column="2" Grid.Row="4" />	
            <Label Content="=" HorizontalAlignment="Center" Name="Label18" VerticalAlignment="Center" Grid.Column="3" Grid.Row="4" />	
            <TextBox Grid.Column="4" Grid.Row="1" Height="24" HorizontalAlignment="Center" Name="sum" VerticalAlignment="Center" MinWidth="60" />	
            <TextBox Grid.Column="4" Grid.Row="2" Height="24" HorizontalAlignment="Center" Name="difference" VerticalAlignment="Center" MinWidth="60" />	
            <TextBox Grid.Column="4" Grid.Row="3" Height="24" HorizontalAlignment="Center" Name="product" VerticalAlignment="Center" MinWidth="60" />	
            <TextBox Grid.Column="4" Grid.Row="4" Height="24" HorizontalAlignment="Center" Name="quotient" VerticalAlignment="Center" MinWidth="60" />	
            <Button Content="Start the quiz" Grid.Column="2" Grid.Row="5"  HorizontalAlignment="Center" Name="startButton" VerticalAlignment="Center" Click="startButton_Click"  />	
            <WindowsFormsHost   Name="WindowsFormsHost1">	
                <self:UserControl1 x:Name="myControl"  />	
            </WindowsFormsHost>	
        </Grid>	
    </Window>		
    


  6. MainWindow.xamlコードの解説
    (1)<Window>階層1:クラス:以下の記載が特別です。
     xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
     上記の記載はUserControlを使用するための記載です。
     xmlns:self="clr-namespace:WpfMaze"
     上記の記載はWpfMazeソリューションを使用するための記載です。
    (2) <WindowsFormsHost x:Name="wfHost" Grid.Row="0">
    <self:UserControl1 x:Name="myControl" />
    </WindowsFormsHost>
     上記の記載でUserControl1の使用条件を設定します。名前は"myControl" となります。
    (3)Grid機能を使用してLabelとTextBoxとButtonを配置します。


  7. MainWindow.xaml.csの全コード
    using System;
    using System.Windows;
    
    namespace WpfMathQuiz
    {
        public partial class MainWindow : Window
        {
            Random randomizer = new Random();
            int addend1;
            int addend2;
            int minuend;
            int subtrahend;
            int multiplicand;
            int multiplier;
            int dividend;
            int divisor;
            int timeLeft;
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void startButton_Click(object sender, RoutedEventArgs e)
            {
                StartTheQuiz();
                startButton.IsEnabled = false;
                myControl.UC = this;
            }
    
            public void StartTheQuiz()
            {
                // Fill in the addition problem.
                addend1 = randomizer.Next(51);
                addend2 = randomizer.Next(51);
                plusLeftLabel.Content = addend1.ToString();
                plusRightLabel.Content = addend2.ToString();
                sum.Text = "0";
    
                // Fill in the subtraction problem.
                minuend = randomizer.Next(1, 101);
                subtrahend = randomizer.Next(1, minuend);
                minusLeftLabel.Content = minuend.ToString();
                minusRightLabel.Content = subtrahend.ToString();
                difference.Text = "0";
    
                // Fill in the multiplication problem.
                multiplicand = randomizer.Next(2, 11);
                multiplier = randomizer.Next(2, 11);
                timesLeftLabel.Content = multiplicand.ToString();
                timesRightLabel.Content = multiplier.ToString();
                product.Text = "0";
    
                // Fill in the division problem.
                divisor = randomizer.Next(2, 11);
                int temporaryQuotient = randomizer.Next(2, 11);
                dividend = divisor * temporaryQuotient;
                dividedLeftLabel.Content = dividend.ToString();
                dividedRightLabel.Content = divisor.ToString();
                quotient.Text = "0";
    
                // Start the timer.
                timeLeft = 30;
                timeLabel.Content = "30 seconds";
                myControl.Timer1.Start();
            }
    
            private bool CheckTheAnswer()
            {
                if ((addend1 + addend2 == Convert.ToInt32(sum.Text))
            && (minuend - subtrahend == Convert.ToInt32(difference.Text))
            && (multiplicand * multiplier == Convert.ToInt32(product.Text))
            && (dividend / divisor == Convert.ToInt32(quotient.Text)))
                { return true; }
                else
                { return false; }
            }
            public void Timer_Tick(object sender, EventArgs e)
            {
                if (CheckTheAnswer())
                {
                    myControl.Timer1.Stop();
                    MessageBox.Show("You got all the answers right!", "Congratulations");
                    startButton.IsEnabled = true;
                }
                else if (timeLeft > 0)
                {
                    timeLeft--;
                    timeLabel.Content = timeLeft + " seconds";
                }
                else
                {
                    myControl.Timer1.Stop();
                    timeLabel.Content = "Time's up!";
                    MessageBox.Show("You didn't finish in time.", "Sorry");
                    sum.Text = Convert.ToString( addend1 + addend2);
                    difference.Text = Convert.ToString(minuend - subtrahend);
                    product.Text =Convert.ToString( multiplicand * multiplier);
                    quotient.Text =Convert.ToString( dividend / divisor);
                    startButton.IsEnabled = true;
                }
            }
        }
    }


  8. MainWindow.xaml.csコードの解説
    (1)myControl.UC = this;は特別なコードです。UserControl1クラスで Public MainWindow UC; とし、変数UCをMainWindow型で生成します。
      thisはMainWindowの実体であり、UserControl1クラスにMainWindowの実体を渡します。
    (2)public void Timer_TickはUserControl1クラスから呼び出されます。
    (3)sum.Value = 0→ sum.Text = "0"はテキストボックスに変更したための変更です。
    (4)addend1 + addend2 == Convert.ToInt32(sum.Text)もテキストボックスに変更したための変更です。


  9. Public Class UserControl1クラスのコード
    using System;
    using System.Windows.Forms;
    
    namespace WpfMathQuiz
    {
        public partial class UserControl1 : UserControl
        {
            public MainWindow UC;
            public UserControl1()
            { InitializeComponent();}
    
            private void Timer1_Tick(object sender, EventArgs e)
            { UC.Timer_Tick(sender, e);}
        }
    }
    


  10. Public Class UserControl1クラスのコード解説
    (1)private void Timer1_Tickは自動的にUserControl1クラスに設定されます。
    (2)主要コードはMainWindowクラスに集中させる都合上、MainWindowクラスのTimer_Tickを呼び出す必要があります。


    感想:
    (1)パーツの変更を行うと、若干ですがコードの変更を伴いました。







34章:WPF絵合わせゲームの作成に行く。

トップページに戻る。