3

いつも Stack Overflow に問題を投稿するわけではありませんが、投稿する場合は、通常、問題の投稿が完了する前に解決策を見つけます。:-) 真剣に、BindingSource の奇妙な動作が発生しています。論理的な説明が見つからず、あなたの助けが必要です。

NET 4 を使用し、EntityFramework 4 を介して SQL データベースを読み取り、BindingList に格納されている ViewModel のリストに結果を書き込みます。これは、BindingSource を介して DataGridView にバインドされます。DataGridView の下には、DataGridView と同じ BindingSource にバインドされたチェック ボックス、テキスト フィールド、コンボ ボックスなどのさまざまなフィールドがあります。そうすれば、DataGridView からアイテムを選択すると、それらのすべてのフィールドが現在選択されている DataGridView アイテムで更新されます。

データベースに次のように定義された 2 つのテーブルがあるとします。

Table name: Country
-------------------
ID: integer, PK
Name: nvarchar

Table name: City
----------------
ID: integer, PK
CountryID: integer, FK to Country
Name: nvarchar

次のように定義された「Citizen」というデータベースにテーブルがあるとしましょう。

Table name: Citizen
-------------------
ID: integer, PK
CityID: integer, FK to City
Name: nvarchar
... (and other irrelevant fields)

DataGridView はBindingList<CitizenViewModel>、「CitizenViewModel」が次のように定義されている場所にバインドされます。

class CitizenViewModel
{
    public int ID { get; set; }
    public int CityID { get; set; }
    public string Name { get; set; }
    public int CountryID { get; set; }

    public CitizenViewModel(Citizen c)
    {
        this.ID = c.ID;
        this.CityID = c.CityID;
        this.Name = c.Name;
        this.CountryID = c.City.CountryID;
    }
}

DGV の BindingSource に名前を付けましょうcitizenViewModelBindingSource

フォームには と の 2 つのコンボ ボックスがあり、どちらもとタイプの BindingSources にそれぞれバインドされてcmbCountryおり、両方のコンボ ボックスで "DisplayMember" が "Name" に設定され、"ValueMember" が "ID" に設定されています。のプロパティは同じバインド元のプロパティにバインドされ、 のプロパティはプロパティにバインドされるため、DGV で選択されている項目に応じて、コンボ ボックスに表示される値が変化します。cmbCityCountryCitySelectedValuecmbCountryCountryIDcitizenViewModelBindingSourceSelectedValuecmbCityCityID

の後ろにあるCurrentChangedイベントを扱っているので、選択した国を変更すると、その選択した国の都市が表示されます。countryBindingSourcecmbCountrycmbCity

private void countryBindingSource_CurrentChanged(object sender, EventArgs e)
{
    // Get the list of Cities that belong to the selected Country
    cityBindingSource.DataSource = GetCities(((Country)countryBindingSource.Current).ID);
}

問題は次のとおりです。結果セットに 5 つの行があり、そのうち 2 つの CountryID は同じですが CityID が異なり、残りの 3 つの CountryID と CityID がすべて異なるとします。同じ CountryID を持つ 2 つの項目の 1 つを選択してから、同じ CountryID を持つもう 1 つの項目を選択すると、それに応じて都市のコンボ ボックスが更新されます。ただし、最初に同じ CountryID を持つこれら 2 つのうちの 1 つを選択し、次に異なる CountryID を持つそれらのいずれかを選択し、最終的に同じ CountryID を持つ他の行を選択すると、バインディング ソースは魔法のように同じ CityID を以前に選択した行と同じに割り当てます。国 ID。混乱しますか?例を挙げて説明します (不要なフィールドは省略します)。

結果:
1. 名前: John Doe; 国: 米国; 都市: シアトル
2. 名前: ジョン・スミス; 国: カナダ; 都市: モントリオール
3. 名前: マイケル・オーウェン。国: イングランド; 都市: リバプール
4. 名前: ジョージ・ブッシュ。国: 米国; 都市: ワシントン
5. 名前: ウラジミール・プーチン; 国: ロシア; 都市: モスクワ

John Doe を選択すると、コンボ ボックスには USA と Seattle と表示されます。
ジョージ ブッシュを選択すると、コンボ ボックスには USA と Washington と表示されます。
John Doe を選択すると、コンボ ボックスには USA と Seattle と表示されます。
ジョージ ブッシュを選択すると、コンボ ボックスには USA と Washington と表示されます。だから、まだ大丈夫です。
Michael Owen を選択します。コンボ ボックスには、イングランドとリバプールが表示されます。
John Doe を選択すると、コンボ ボックスには USA と Seattle と表示されます。
これを見てください。George Bush を選択すると、コンボ ボックスには USA と Seattle と表示されます (本来の USA と Washington ではありません)。バインディング ソースは、ジョージ ブッシュの CityID を変更しました!

問題について書き終えましたが、解決策が頭に浮かびません。これが発生する理由と、この動作を回避する方法を教えてください。

編集

「SelectedValue」のバインドを解除し、関数を次のようcmbCityに変更することで問題を解決しました。countryBindingSource_CurrentChanged

    private void countryBindingSource_CurrentChanged(object sender, EventArgs e)
    {
        if (citizenViewModelBindingSource.Current != null)
        {
            cityBindingSource.DataSource = GetCities(((Country)countryBindingSource.Current).ID);
            // update the combo box manually
            cmbCity.SelectedValue = ((CitizenViewModel)citizenViewModelBindingSource.Current).CityID;
        }
    }

しかし、これは私にはハッキングのように思えます。なぜこれが起こるのかについて誰かが手がかりを持っているなら、私はこの質問を開いたままにします.

4

1 に答える 1