3

私はMVVMを学んでいます。

ViewModel の ObservableCollection プロパティから 2 つのコンボボックスを埋める View があります (例: プロパティ " Oc1 " & " Oc2 ")。また、 Oc2が依存するOc1の選択された項目(例: プロパティ " SelVal ") にバインドされたプロパティがあるため、プロパティSelValが変更されると、Oc2はデータベースからデータを再取得する必要があります。

今、私は解決策を思いつきました。それは私の状況ではうまくいきますが、getアクセサーの原則に準拠していないようです。解決?

私の現在の解決策は次のとおりです。

Oc2getアクセサーはデータベースにクエリを実行し、プライベート フィールドをデータベースから返された値 (ビューが使用する値) に設定します。したがって、SetValが変更されると、 SetValセットアクセサーで this.RaisePropertyChanged(" Oc2 ") を呼び出すだけで、View はOc2を要求します。これにより、データベースが照会され、更新されたリストが返されます。問題は、 getアクセサーに値を割り当てているため、意図したとおりにgetアクセサーを使用していないことです。しかし、私が気に入っているのは、それが自己完結型であることです (つまり、コンストラクターで呼び出してから、SelValセットで再度呼び出す必要がある "BindOc2" メソッドは必要ありません)。 アクセサー)。お知らせ下さい。そして、より良い方法は何ですか?

4

5 に答える 5

2

はい、別のプロパティのPropertyChangedを上げることは少しハッキーな感じがしますが、それはそれほど悪くない私見です。

より自然な方法は、データベースがSelValセッターをプルすることです。これがデータの変更をトリガーするためです。Oc2次に、必要に応じて自動的にを上げる結果に設定しPropertyChangedます。

これに関する唯一の問題は、Oc2ゲッターにアクセスしたことがない場合、dbの結果を不必要にプルする可能性があることですが、ビューが常にそれらを必要とすることを知っているので、このソリューションに変更したくなるでしょう。

于 2012-06-12T08:30:51.000 に答える
2

あなたの疑いは正しいです。この方法では、MVVM モデルが壊れ、Expression Blend SDKで利用可能なSystem.Windows.Interactivityのトリガーのような、作業を簡素化できるメカニズムを使用できません。

ゲッターにデータをロードすると、問題が発生します。モデルをデータ アクセス コードにバインドし、同じプロパティにさまざまな問題を混在させることで、テストを難しくし、コードをより複雑にします。さらに、マーフィーの法則により、ある時点で、データベースからリロードせずにプロパティを設定したいだけになると規定されています。

より良い解決策は、コマンドまたはトリガーによって呼び出すことができる別のメソッドでデータ読み込みコードを抽出することです。このメソッドは、Oc2 コレクションの内容を変更するか、単に新しいコレクションに置き換えます。いずれにせよ、プロパティ セッターは適切な通知を生成し、2 番目のコンボが更新されます。

次の例は、同様の SO 質問でのファビエンの回答からのものです。

<ComboBox x:Name="fileComboBox" ItemsSource="{Binding FileList, Mode=TwoWay}">                  
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction 
                        Command="{Binding SelectionChangedCommand}"
                        CommandParameter="{Binding SelectedItems,           
                        ElementName=fileComboBox}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>

    </ComboBox>

ほとんどのフレームワークは、この設計をサポートしています。Caliburn.Microは 、UI イベントが発生したときに ViewModel メソッドを呼び出すアクションと、トリガー XAML および対応するコマンドの記述を避けるためのショートカット構文を提供します。イベントを ViewModel メソッドに接続するだけです。XAML は次のように単純にすることができます。

<ComboBox x:Name="Oc1" 
    cal:Message.Attach="[Event SelectionChanged] = 
                        [Action ReloadFor($this.SelectedItem)]" />

$this値は、ComboBox 自体を参照する別の省略形です。

トリガーを使用したくない場合は、コンボの SelectedItem プロパティを ViewModel プロパティにバインドし、このプロパティが変更されるたびに Reload メソッドを実行できます。

<ComboBox ... SelectedItem={Binding CurrentOC2,Mode=TwoWay} />
于 2012-06-12T07:00:38.527 に答える
1

つまり、言い換えると、Category、CurrentCategory、およびSubCategoryに似たものがあります。CurrentCategoryが変更された場合、SubCategoryを更新する必要があります。

あなたのやり方は大丈夫だと思います。特にMVVMでは、この種のことはいたるところに見られます。MVVMの外部では、遅延読み込みシナリオでプロパティゲッターがデータベースにアクセスするのはかなり一般的です(通常、すべてをインライン化するのではなく、ある種のサービスメソッドを呼び出します)。

于 2012-06-12T05:09:13.797 に答える
1

これらのデータが変更されていない場合は、それをビューモデルに含めることができます。

常にデータベースにクエリを実行することを最初の選択肢にすべきではありません。

これは非常に簡単な方法で行うことができます。

Dictionary<string, List<string>> cache;
...
List<string> subCat;
if cache.TryGetValue (selVal, out subCat) 
{
    // no need to call database
}
else
{
   // else call database
   // insert result in cache
}
于 2012-06-12T06:13:31.933 に答える
1

やり方は結構です。プロパティの set および get メソッドは、通常、この種のバインディングに適しています

于 2012-06-12T03:24:18.137 に答える