【WPF】別ウィンドウに値を受け渡して、データを更新できるようにしてみた

2017年8月19日C#,開発

おはようございます。

昨日に引き続き、
モーダル表示した子ウィンドウの話です。

こういった画面を作る際に必要となるのが、親画面から子画面(逆もまたしかり)へのデータ渡しですよね。

ということで、
今回はデータの修正を別ウィンドウで行うように修正するついでに、親から子へデータを渡す方法を試してみます。

プログラムは前回のものを。

https://www.doraxdora.com/blog/2017/08/18/post-2073/

スポンサーリンク

画面の変更

SubWindow.xaml
更新ボタンを追加し、デフォルトを非表示状態にする。

<Mah:MetroWindow x:Class="WpfApp1.SubWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        mc:Ignorable="d"
        Title="追加" Height="300" Width="300"
        GlowBrush="{DynamicResource AccentColorBrush}"
        Icon="/WpfApp1;component/Resource/Cat.ico"
        BorderThickness="1"
        WindowStartupLocation="CenterOwner"
        >
    <Window.Resources>
        <ResourceDictionary Source="/Style/StyleDic.xaml"/>
    </Window.Resources>
    <Grid>
        <Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}" RenderTransformOrigin="0.522,0.893"/>
        <TextBox x:Name="txt_name" Margin="61,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100"  Style="{StaticResource MetroTextBox}"/>
        <Label Content="性別:" Margin="10,54,0,0" Style="{StaticResource lb-normal}"/>
        <ComboBox x:Name="cmb_sex" HorizontalAlignment="Left" Margin="61,54,0,0" VerticalAlignment="Top" Width="50">
            <ComboBoxItem Content="♂" HorizontalAlignment="Left" Width="50"/>
            <ComboBoxItem Content="♀" HorizontalAlignment="Left" Width="50"/>
        </ComboBox>
        <ComboBox x:Name="cmb_kind" HorizontalAlignment="Left" Margin="61,140,0,0" VerticalAlignment="Top" Width="150"/>
        <Label Content="年齢:" Margin="10,98,0,0" Style="{StaticResource lb-normal}"/>
        <TextBox x:Name="txt_age" Margin="61,98,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="50"  Style="{StaticResource MetroTextBox}"/>
        <Label Content="種別:" Margin="10,143,0,0" Style="{StaticResource lb-normal}"/>
        <Label Content="好物:" Margin="10,186,0,0" Style="{StaticResource lb-normal}"/>
        <TextBox x:Name="txt_favorite" Margin="61,186,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200"  Style="{StaticResource MetroTextBox}"/>
        <Button x:Name="btn_cansel" Content="キャンセル" HorizontalAlignment="Left" Margin="125,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_cansel_Click"/>
        <Button x:Name="btn_add" Content="追加" HorizontalAlignment="Left" Margin="205,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_add_Click"/>
        <Button x:Name="btn_mod" Content="更新" HorizontalAlignment="Left" Margin="205,231,0,0" VerticalAlignment="Top" Width="75" Click="btn_mod_Click" Visibility="Collapsed"/>
    </Grid>
</Mah:MetroWindow>


プログラム修正

コンストラクタに引数を追加

親画面から値を受け取るために引数を追加します。
SubWindow.xaml.cs

    public SubWindow()
    を
    public SubWindow(CatModel SelectedCat)
    に変更する

グローバル変数の追加

更新時に参照するためにグローバルな変数に受け取ったデータを設定します。
SubWindow.xaml.cs

public CatModel SelectedCat { set; get; }

初期化処理の修正

追加、更新でボタンの表示切替、及び画面へのデータ設定を行うようにします。
SubWindow.xaml.cs

            public SubWindow(CatModel SelectedCat)
            {
                InitializeComponent();
    
                // データを取得
                // 種別マスタを取得してコンボボックスに設定する
                using (var context = new PgDbContext())
                {
                    var mstKind = context.Kinds;
                    IQueryable<Kind> result = from x in mstKind orderby x.KindCd select x;
                    var list = result.ToList();
    
                    // コンボボックスに設定
                    this.cmb_kind.ItemsSource = list;
                    this.cmb_kind.DisplayMemberPath = "KindName";
    
                    if (SelectedCat == null)
                    {
                        // 追加処理の場合
                        this.Title = "追加";
                        this.btn_add.Visibility = Visibility.Visible;
                        this.btn_mod.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        this.SelectedCat = SelectedCat;
    
                        // 更新処理の場合
                        this.Title = "更新";
                        this.btn_add.Visibility = Visibility.Collapsed;
                        this.btn_mod.Visibility = Visibility.Visible;
    
                        // 値の設定
                        this.txt_name.Text = SelectedCat.Name;
                        foreach (ComboBoxItem i in this.cmb_sex.Items)
                        {
                            if (i.Content.ToString().Trim() == SelectedCat.Sex.Trim())
                            {
                                this.cmb_sex.SelectedItem = i;
                            }
                        }
                        this.txt_age.Text = SelectedCat.Age.ToString();
                        foreach (Kind k in list)
                        {
                            if (k.KindCd == SelectedCat.Kind)
                            {
                                this.cmb_kind.SelectedItem = k;
                                break;
                            }
                        }
                        this.txt_favorite.Text = SelectedCat.Favorite;
                    }
                }
            }
    

更新処理の追加

更新ボタンクリックイベントを追加します。
SubWindow.xaml.cs

        /// <summary>
        /// 更新ボタンクリックイベント.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_mod_Click(object sender, RoutedEventArgs e)
        {
            this.IsCancel = false;

            // データを更新する
            using (var context = new PgDbContext())
            {
                // 対象のテーブルオブジェクトを取得
                var table = context.Cats;
                // テーブルから対象のデータを取得
                var target = table.Single(x => x.No == SelectedCat.No);
                // データ変更
                target.Name = this.txt_name.Text;
                target.Sex = (this.cmb_sex.SelectedItem as ComboBoxItem).Content.ToString();
                target.Age = int.Parse(this.txt_age.Text);
                target.Kind = (this.cmb_kind.SelectedItem as Kind).KindCd;
                target.Favorite = this.txt_favorite.Text;

                // DBの変更を確定
                context.SaveChanges();

                MessageBox.Show("データを更新しました。");
            }

            this.Close();
        }

追加ボタン押下処理の修正

SubWindowのコンストラクタに引数を追加したが、追加処理では特に子画面に渡すものがないので null を指定。
MainWindow.xaml.cs

        /// <summary>
        /// 追加ボタンクリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void add_button_Click(object sender, RoutedEventArgs e)
        {
            logger.Info("追加ボタンクリック");
            var win = new SubWindow(null);
            win.Owner = GetWindow(this);
            win.ShowDialog();

            if (!win.IsCancel) {
                // データ再検索
                searchData();
            }
        }

更新ボタン押下処理の修正

画面で選択されたデータを取得し子画面へ渡すように。
MainWindow.xaml.cs

        /// <summary>
        /// 更新ボタンクリックイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void upd_button_Click(object sender, RoutedEventArgs e)
        {
            logger.Info("更新ボタンクリック");

            // 選択チェック
            if (this.dataGrid.SelectedItem == null)
            {
                MessageBox.Show("更新対象を選択してください。");
                return;
            }

            // 選択されているデータを取得
            CatModel cat = this.dataGrid.SelectedItem as CatModel;
            var win = new SubWindow(cat);
            win.Owner = GetWindow(this);
            win.ShowDialog();


            if (!win.IsCancel)
            {
                // データ再検索
                searchData();
            }
        }

起動してみる

検索後画面

対象を選択して「更新」ボタンをクリックします。

別ウィンドウ表示

別ウィンドウが表示され、選択されたデータが各項目に反映されています。

内容の変更

データを修正し、「更新」ボタンをクリックします。

確認メッセージ表示

確認メッセージが表示されます。

データ再検索

データが再検索され、更新が反映されていることが確認できました。

まとめ

無事に親画面から子画面へとデータを渡して処理することができました。
引数をオブジェクトの配列なんかにすると複数のパラメータを渡すことも可能ですね

という感じで、今回はここまでです。

ではでは。

スポンサーリンク


関連するコンテンツ

2017年8月19日C#,開発C#,WPF,プログラミング

Posted by doradora