Windows Presentation Foundation (WPF) に入門してみる part 6 Gridを新規作成するメソッドとコントロールを追加するメソッドを作る

2021年10月2日記事を修正しました。
「AddChild」という名前の拡張メソッドを追加しています。



はじめに

xamlファイルを全く記述しないでC#のコードだけでGUIを構築するのが目標です。
今回も「XAML」「バインディング」などの知識ゼロのまま進めていきます。

Gridを多用してGUIを構築してきたのですがGridを新規作成してRowDefinition、ColumnDefinitionを追加していくのが面倒くさく感じます。

Gridを新規作成するメソッドを用意してコードの簡略化を図りたいと思います。

Gridを新規作成するメソッド

こういったものをあらかじめ用意しておくこととします。

using System.Linq;
using System.Windows;
using System.Windows.Controls;

static class Myfunc
{
    public static Grid newGrid(string row, string col) //引数はカンマ区切りで
    {
        Grid grid = new();

        string[] grid_row = row.Split(",");
        string[] grid_col = col.Split(",");

        if (grid_row.Count() > 1)
        {
            foreach (string each in grid_row)
            {
                if (int.TryParse(each, out int each_num))
                {
                    grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(each_num, GridUnitType.Star) });
                }
                else
                {
                    grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
                }
            }
        }
        if (grid_col.Count() > 1)
        {
            foreach (string each in grid_col)
            {
                if (int.TryParse(each, out int each_num))
                {
                    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(each_num, GridUnitType.Star) });
                }
                else
                {
                    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
                }
            }
        }
        return grid;
    }
}

利用例

前回のコードを書き換えてみます。

書き換え後

private void WindowSetting()
{
    //WindowStyle = WindowStyle.None;
    WindowState = WindowState.Maximized;
    Title = "けいさん";

    Grid mainGrid = Myfunc.newGrid("2,8", "");
    Content = mainGrid;

    Grid upperPanel = Myfunc.newGrid("1,1", "1,1,1,1,1,1,1,1,1,1");
    upperPanel.Margin = new Thickness(3);
    Grid.SetRow(upperPanel, 0);
    mainGrid.Children.Add(upperPanel);

    for(int i = 0; i < 20; i++)
    {
        starImage[i] = new();
        starImage[i].Source = null;
        Grid.SetColumn(starImage[i], i % 10);
        Grid.SetRow(starImage[i], i / 10);
        upperPanel.Children.Add(starImage[i]);
    }

    Grid lowerPanel = Myfunc.newGrid("", "7,2");
    Grid.SetRow(lowerPanel, 1);
    mainGrid.Children.Add(lowerPanel);

    Grid leftPanel = Myfunc.newGrid("4,1", "");
    Grid.SetColumn(leftPanel, 0);
    lowerPanel.Children.Add(leftPanel);

    Grid questionBox = Myfunc.newGrid("", "2,1,2");
    Grid.SetRow(questionBox, 0);
    leftPanel.Children.Add(questionBox);

    Viewbox l_questionBox = new() { Child = l_question };
    Viewbox c_questionBox = new() { Child = c_question };
    Viewbox r_questionBox = new() { Child = r_question };
    
    Grid.SetColumn(questionBox, 0);
    Grid.SetColumn(c_questionBox, 1);
    Grid.SetColumn(r_questionBox, 2);

    questionBox.Children.Add(l_questionBox);
    questionBox.Children.Add(c_questionBox);
    questionBox.Children.Add(r_questionBox);

    Grid startButtonGrid = Myfunc.newGrid("", "1,1,1");
    Grid.SetRow(startButtonGrid, 1);
    leftPanel.Children.Add(startButtonGrid);

    startButton.Click += PushStartButton;
    Grid.SetColumn(startButton, 1);
    startButtonGrid.Children.Add(startButton);

    Grid rightPanel = Myfunc.newGrid("1,*", "");
    Grid.SetColumn(rightPanel, 1);
    lowerPanel.Children.Add(rightPanel);

    //右上
    Viewbox upperRightBox = new();
    upperRightBox.Child = yourInput;
    Grid.SetRow(upperRightBox, 0);
    rightPanel.Children.Add(upperRightBox);

    //右下
    Grid lowerRight = Myfunc.newGrid("1,1,1,1", "1,1,1");
    lowerRight.Height = 400;
    lowerRight.Width = 300;

    Viewbox numberKeyBox = new() { Child = lowerRight };
    Grid.SetRow(numberKeyBox, 1);
    rightPanel.Children.Add(numberKeyBox);

    //数字ボタン
    for (int i = 0; i < 10; i++)
    {
        numberkeys[i] = new() { Margin = new Thickness(3) };
        numberkeys[i].Content = new Viewbox() { Child = new Label() { Content = i.ToString() } };
        numberkeys[i].Name = $"button_{i}";
        numberkeys[i].Click += PushNumberKey;
        Grid.SetRow(numberkeys[i], (9 - i) / 3);
        if (i == 0)
        {
            Grid.SetColumn(numberkeys[i], 0);
        }
        else
        {
            Grid.SetColumn(numberkeys[i], (i + 2) % 3);
        }
        lowerRight.Children.Add(numberkeys[i]);
    }
    numberkeys[10] = new() { 
        Margin = new Thickness(3), 
        Content = new Viewbox() { Child = new Label() { Content = "けす" } } 
    };
    numberkeys[10].Click += PushClearKey;
    Grid.SetColumn(numberkeys[10], 1);
    Grid.SetColumnSpan(numberkeys[10], 2);
    Grid.SetRow(numberkeys[10], 3);
    lowerRight.Children.Add(numberkeys[10]);

    foreach (Button each in numberkeys) each.IsEnabled = false;
}

書き換え前

private void WindowSetting()
{
    //WindowStyle = WindowStyle.None;
    WindowState = WindowState.Maximized;
    Title = "けいさん";

    Grid mainGrid = new();
    mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(2, GridUnitType.Star) });
    mainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(8, GridUnitType.Star) });
    Content = mainGrid;

    Grid upperPanel = new() { Margin = new Thickness(3) };
    for(int i = 0; i < 2 ; i++)
    {
        upperPanel.RowDefinitions.Add(new RowDefinition());
    }
    for(int i = 0; i < 10; i++)
    {
        upperPanel.ColumnDefinitions.Add(new ColumnDefinition());
    }
    Grid.SetRow(upperPanel, 0);
    mainGrid.Children.Add(upperPanel);

    for(int i = 0; i < 20; i++)
    {
        starImage[i] = new();
        starImage[i].Source = null;
        Grid.SetColumn(starImage[i], i % 10);
        Grid.SetRow(starImage[i], i / 10);
        upperPanel.Children.Add(starImage[i]);
    }

    Grid lowerPanel = new();
    lowerPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(7, GridUnitType.Star) });
    lowerPanel.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
    Grid.SetRow(lowerPanel, 1);
    mainGrid.Children.Add(lowerPanel);

    Grid leftPanel = new();
    leftPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(4, GridUnitType.Star) });
    leftPanel.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
    Grid.SetColumn(leftPanel, 0);
    lowerPanel.Children.Add(leftPanel);

    Grid questionBox = new();
    questionBox.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
    questionBox.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
    questionBox.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
    Grid.SetRow(questionBox, 0);
    leftPanel.Children.Add(questionBox);

    Viewbox l_questionBox = new() { Child = l_question };
    Viewbox c_questionBox = new() { Child = c_question };
    Viewbox r_questionBox = new() { Child = r_question };
    
    Grid.SetColumn(questionBox, 0);
    Grid.SetColumn(c_questionBox, 1);
    Grid.SetColumn(r_questionBox, 2);

    questionBox.Children.Add(l_questionBox);
    questionBox.Children.Add(c_questionBox);
    questionBox.Children.Add(r_questionBox);

    Grid startButtonGrid = new();
    startButtonGrid.ColumnDefinitions.Add(new ColumnDefinition());
    startButtonGrid.ColumnDefinitions.Add(new ColumnDefinition());
    startButtonGrid.ColumnDefinitions.Add(new ColumnDefinition());
    Grid.SetRow(startButtonGrid, 1);
    leftPanel.Children.Add(startButtonGrid);

    startButton.Click += PushStartButton;
    Grid.SetColumn(startButton, 1);
    startButtonGrid.Children.Add(startButton);
    
    Grid rightPanel = new();
    rightPanel.RowDefinitions.Add(new RowDefinition());
    rightPanel.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
    Grid.SetColumn(rightPanel, 1);
    lowerPanel.Children.Add(rightPanel);

    //右上
    Viewbox upperRightBox = new();
    upperRightBox.Child = yourInput;
    Grid.SetRow(upperRightBox, 0);
    rightPanel.Children.Add(upperRightBox);

    //右下
    Grid lowerRight = new() { Width = 300, Height = 400 };
    Viewbox numberKeysBox = new() { Child = lowerRight };
    Grid.SetRow(numberKeysBox, 1);
    rightPanel.Children.Add(numberKeysBox);

    //数字ボタン
    for(int i = 0; i < 3; i++)
    {
        lowerRight.ColumnDefinitions.Add(new ColumnDefinition());
    }
    for(int i = 0; i < 4; i++)
    {
        lowerRight.RowDefinitions.Add(new RowDefinition());
    }
    for (int i = 0; i < 10; i++)
    {
        numberkeys[i] = new() { Margin = new Thickness(3) };
        numberkeys[i].Content = new Viewbox() { Child = new Label() { Content = i.ToString() } };
        numberkeys[i].Name = $"button_{i}";
        numberkeys[i].Click += PushNumberKey;
        Grid.SetRow(numberkeys[i], (9 - i) / 3);
        if (i == 0)
        {
            Grid.SetColumn(numberkeys[i], 0);
        }
        else
        {
            Grid.SetColumn(numberkeys[i], (i + 2) % 3);
        }
        lowerRight.Children.Add(numberkeys[i]);
    }
    numberkeys[10] = new() { 
        Margin = new Thickness(3), 
        Content = new Viewbox() { Child = new Label() { Content = "けす" } } 
    };
    numberkeys[10].Click += PushClearKey;
    Grid.SetColumn(numberkeys[10], 1);
    Grid.SetColumnSpan(numberkeys[10], 2);
    Grid.SetRow(numberkeys[10], 3);
    lowerRight.Children.Add(numberkeys[10]);

    foreach (Button each in numberkeys) each.IsEnabled = false;
}

劇的にすっきりしました。

コントロールを追加する拡張メソッド

public static Grid AddChild(this Grid grid, UIElement element, int row, int col, int row_span, int col_span)
{
    Grid.SetRow(element, row);
    Grid.SetRowSpan(element, row_span);
    Grid.SetColumn(element, col);
    Grid.SetColumnSpan(element, col_span);
    grid.Children.Add(element);

    return grid;
}

さいごに

間違いや改善点があればコメント頂けましたら幸いです。

前回までの記事

Windows Presentation Foundation (WPF) に入門してみる part 1 - パソコン関連もろもろ
Windows Presentation Foundation (WPF) に入門してみる part 2 Imageを並べる - パソコン関連もろもろ
Windows Presentation Foundation (WPF) に入門してみる part 3 ComboBoxを使う - パソコン関連もろもろ
Windows Presentation Foundation (WPF) に入門してみる part 4 Viewboxを使う - パソコン関連もろもろ
Windows Presentation Foundation (WPF) に入門してみる part 5 テンキー付きの計算ドリルを作る - パソコン関連もろもろ