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

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

ただいまの
回答率

90.84%

  • WPF

    641questions

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

  • SQL Server

    537questions

    SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

  • Entity Framework

    29questions

ComboBoxとデータベースの連動

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 154

mikihiro

score 2

 前提

環境

  • Visual Studio Community 2017 
  • Microsoft SQL Server 2017 Express  
  • Entity Framework (データベースファースト開発) 
  • .NET 4.7 
  • WPF

 現在、行っている方法

  • EFで生成した、CategoryをToListにして、ComboBox.ItemsSourceにセットすることで、名前の表示、IDの取得はできています。
  • Personレコードを表示する時は、PersonのCategoryIDを、ComboBoxにセット( ソースの ■1)
  • Personレコードを登録する時は、ComboBoxのSelectedValueを取得して、表示しているPersonレコードのCategoryIDにセットしています(ソースの ■2)。

データベースには、Personテーブルと、Categoryテーブルがあります。
また、データベースから、モデルを作成してあります。
イメージ説明
Categoryには、次のようにレコードを登録してあります。

 行いたいこと

行いたいことは、Comboboxで、選択した値を自動的に連動することです。

TextBoxでは、{Binding CategoryID}されているので、テキストボックスに数値を入力すれば、後は、context.SaveChanges();で、データベースに登録されます。同様に、Comboboxでも、Binding か何かで、Person.CategoryIDに該当する名前を表示し、名前を選択した場合は、その値が自動的にcontextに反映されて、context.SaveChanges()で保存できないか、いろいろ調べましたが分かりませんでした。

連動させれば、■1と■2の部分は不要になると思います。
なにか、適切な方法はないでしょうか?

 実行画面

イメージ説明

 XAMLのComboBoxと、TextBox部分

<ComboBox x:Name="comboTest"  HorizontalAlignment="Left" Margin="168,55,0,0" VerticalAlignment="Top" Width="120"/>

<TextBox x:Name="categoryIDTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding CategoryID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>

 該当のソースコード

namespace ComboTest
{
 
    public partial class MainWindow : Window
    {
        TestDBEntities context = new TestDBEntities();
         CollectionViewSource personViewSource;

        public MainWindow()
        {
            InitializeComponent();
            personViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("personViewSource")));

        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            context.People.Load();
            context.Categories.Load();

            // ここではPersonのID1を表示
            var query = from item in context.People
                        where item.ID == 1
                        select item;

            personViewSource.Source = query.ToList();

            Person p = query.First();

            // ComboBoxにソースをセット
            var cList = context.Categories.ToList();
            comboTest.ItemsSource = cList;
            comboTest.DisplayMemberPath = "名前";
            comboTest.SelectedValuePath = "ID";

            // ■1  ComboBoxに表示する値をセットする。
            comboTest.SelectedValue = p.CategoryID;

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            // ■2  ComboBoxの値を反映させる
            Person p = context.People.Where(x => x.ID == 1).First();
            p.CategoryID = (int)comboTest.SelectedValue;



            context.SaveChanges();
        }
    }
}

 補足

<Window x:Class="ComboTest.MainWindow"
        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:ComboTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="572.14" Loaded="Window_Loaded">
    <Window.Resources>
        <CollectionViewSource x:Key="personViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Person}, CreateList=True}"/>
    </Window.Resources>
    <Grid>
        <Grid x:Name="grid1" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="302,96,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
        </Grid>
        <Grid x:Name="grid2" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="127,176,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Content="名前:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
            <TextBox x:Name="名前TextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding 名前, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
        </Grid>
        <ComboBox x:Name="comboTest"  HorizontalAlignment="Left" Margin="168,55,0,0" VerticalAlignment="Top" Width="120"/>


        <Grid x:Name="grid3" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="86,140,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Content="Category ID:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
            <TextBox x:Name="categoryIDTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding CategoryID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
        </Grid>
        <Button Content="登録" HorizontalAlignment="Left" Margin="174,231,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <TextBlock HorizontalAlignment="Left" Margin="298,144,0,0" TextWrapping="Wrap" Text="バインドされている。" VerticalAlignment="Top" Height="23" Width="117"/>
        <TextBlock HorizontalAlignment="Left" Margin="302,56,0,0" TextWrapping="Wrap" Text="バインドされていない。" VerticalAlignment="Top" Height="23" Width="122"/>

    </Grid>
</Window>

 CollectionViewSourceの自動生成

イメージ説明
データソースから追加すると、Window.Resourcesが自動で追加されました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

できればxamlの全文を見せていただきたいところですが難しいでしょうか?
ご対応ありがとうございます。

ただ、TextBoxでそのような形でBindingできているのであれば、
ComboBoxでSelectedValueにCategoryIDをBindingすることで実現可能なような気がします。
下記のサンプルを試していただければと思います。

CollectionViewSourceの動作に自信がありませんが、下記のようにDataContextにpersonViewSourceが
設定されているObject下にComboBoxを置く必要があるかと思います。
一応手元の環境でpersonViewSourceまで選択したCategoryIDが反映されるところまでは動作確認しました。

<Window x:Class="ComboTest.MainWindow"
        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:ComboTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="572.14" Loaded="Window_Loaded">
    <Window.Resources>
        <CollectionViewSource x:Key="personViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Person}, CreateList=True}"/>
    </Window.Resources>
    <!--ここに参照を追加-->
    <Grid DataContext="{StaticResource personViewSource}">
        <Grid x:Name="grid1" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="302,96,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
        </Grid>
        <Grid x:Name="grid2" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="127,176,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Content="名前:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
            <TextBox x:Name="名前TextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding 名前, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
        </Grid>
        <ComboBox x:Name="comboTest"  HorizontalAlignment="Left" Margin="168,55,0,0" VerticalAlignment="Top" Width="120"
                  SelectedValue={Binding CategoryID,UpdateSourceTrigger=PropertyChanged}/>
        <Grid x:Name="grid3" DataContext="{StaticResource personViewSource}" HorizontalAlignment="Left" Margin="86,140,0,0" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Content="Category ID:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
            <TextBox x:Name="categoryIDTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding CategoryID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
        </Grid>
        <Button Content="登録" HorizontalAlignment="Left" Margin="174,231,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <TextBlock HorizontalAlignment="Left" Margin="298,144,0,0" TextWrapping="Wrap" Text="バインドされている。" VerticalAlignment="Top" Height="23" Width="117"/>
        <TextBlock HorizontalAlignment="Left" Margin="302,56,0,0" TextWrapping="Wrap" Text="バインドされていない。" VerticalAlignment="Top" Height="23" Width="122"/>

    </Grid>
</Window>

※念のための確認
このぐらいの操作であればCollectionViewSourceは不要で、
単にWindowのDataContextにPersonを設定すれば動作するように思えますが、
ColectionViewSourceを使用している理由はございますか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/29 15:47

    早速のご回答ありがとうございます。頂いたコードを試してみましたが、うまく機能しませんでした。
    補足に、XAMLを掲載しました。よろしくお願い致します。

    キャンセル

  • 2018/05/29 17:02

    確認までして頂き誠にありがとうございます。このコードで機能しました。助かりました。
    CollectionViewSourceは、データーソースから、追加した時に、自動的に生成されたものです。今後、参考にされる方のために、画像を掲載しておきます。
    Contextの動作などまだよく分かっていませんので、Gridに設定する理屈など、今後勉強していきたいと思います。ありがとうございました。

    キャンセル

  • 2018/05/29 17:18

    無事に動いたようで、よかったです。
    なるほど、そういうことだったのですね。画像の追加、ありがとうございます。
    WPFはMVVMやらBindingやら覚えることが多くて大変だと思います。
    私も最近やっとコツをつかめてきたところです。
    WPFであればそこそこには答えられると思いますのでどんどん質問投げて頂ければと思います。

    キャンセル

  • 2018/05/29 23:36

    WPFや、EntityFramework、xamlは、なじみのなかった技術なので、先人の知恵やQ&Aを読みつつ試行錯誤でやってます。やっかいなのが、新旧入り交じったいろいろな方法があって、何が適しているのかよくわからないところです。ComboBoxのItemsSourceも最初はDataTableにしましたが、EntityFrameworkを利用の場合はそうする必要はなかった、というのも後で分かるなど、なかなか最適解にたどり着かないところが厳しい・・
    また、質問することになると思いますので、その時はよろしくお願い致します。今回はありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • WPF

    641questions

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

  • SQL Server

    537questions

    SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

  • Entity Framework

    29questions