2013-07-25 15 views
6

私は、自分のWPFアプリケーションとそれに続くMVVMでComboBoxを使用しています。 ComboBoxに表示したい文字列のリストがあります。MVVMを使用してコンボボックスの選択項目をリセットします。

XAML:

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem}" /> 

ビューモデル:

public Collection<string> ItemsCollection; // Suppose this has 10 values. 
private string _selectedItem; 
public string SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
     _selectedItem = value; 
     Trigger Notify of property changed. 
    } 
} 

は今、このコードは絶対に正常に動作しています。私はビューから選択することができ、ViewModelで変更を加えることができます。私がViewModelからSelectedItemを変更すると、私のビューでそれを見ることができます。

ここに私が達成しようとしているものがあります。選択したアイテムを私のビューから変更すると、値が良い/悪い(または何か)の選択項目を設定していることを確認する必要があります。私のビューモデルはこのように変わります。

public string SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
     if (SomeCondition(value)) 
      _selectedItem = value;   // Update selected item. 
     else 
      _selectedItem = _selectedItem; // Do not update selected item. 
     Trigger Notify of property changed. 
    } 
} 

私はこのコードとSomeCondition(値)を実行falseを返し、のSelectedItemは、古い文字列値を返しますが、私の見解ではコンボボックス内の項目を選択し、私が選択した値です。だから私は私のコンボボックスに表示されている10文字列のコレクションを持っていると仮定することができます。 2番目と4番目の要素を除くすべての値は良好です(SomeConditionは2番目と4番目の値に対してfalseを返します)。 2番目または4番目の要素selectedItemを選択した場合、変更しないでください。しかし、私のコードはこれを正しく実行していません。 2番目の要素を選択すると、2番目の要素が選択されたまま表示されます。私は自分のコードに何か間違っていることを知っています。しかし、それは何ですか?

+1

これは非常にユーザーフレンドリーなデザインではありません。私がコンボボックスで何かを選んだら、私はそれが私の選択したアイテムであると思っています。代わりに無効なオプションをコンボボックスから削除する必要があります。選択の有効性が別のUI要素の選択された値に基づいている場合、その選択を変更すると、コンボボックスのItemSourceの再構築がトリガーされます。 –

+1

それはすべての項目を表示するための要件であり、変更することはできません。 –

+1

私は、無効なオプションを表示しないこと、またはそれらを灰色にして選択を無効にすることに同意します。これはUIのためです。 –

答えて

14

にXAMLを変更してみてください。まず、私はこれが無効な選択を処理するための推奨されないアプローチであると他の人に同意します。 @blindmeisが示唆するように、IDataErrorInfoはそれを解決する良い方法の一つです。

質問自体に戻ってください。 @Faisal Hafeez氏が何を望んでいるかを満たす解決策は以下のとおりです。

public string SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
     var oldItem=_selectedItem; 
     _selectedItem=value; 
     OnPropertyChanged("SelectedItem") 

     if (!SomeCondition(value)) //If does not satisfy condition, set item back to old item 
      Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => SelectedItem = oldItem), 
               DispatcherPriority.ApplicationIdle); 
    } 
} 

Dispatcherは別のUIの同期中に、いくつかのUIの同期を処理するためのエレガントな方法です。たとえば、この場合、選択のバインド中に選択をリセットする必要があります。

ここでの質問は、まず選択肢を更新する必要がある理由です。これはSelectedItemSelectedValueが別々に割り当てられており、ComboBoxの表示はSelectedItem(おそらくSelectedValue、私はここではわかりません)に依存しないためです。もう1つの興味深い点は、SelectedValueが変更された場合、SelectedItemは変更する必要がありますが、SelectedItemは変更するとSelectedValueを更新しません。したがって、最初に割り当てる必要がないようにSelectedValueにバインドすることを選択できます。

+0

これがうまくいきました。 –

+0

私たちはまったく同じ問題を抱えていて、あなたの回避策が働いています。 また、すべてのアイテムを表示することもできますが、選択することはできません。また、他のアイテムを選択することができない短時間のため、コントロールを無効にしたくない場合もあります。 Selector UIエレメントに常に正しいプロパティ値が表示されるような動作を記述する方法はありますか? – Lumo

3

は、これは非常に興味深い質問です。この

<ComboBox ItemsSource="{Binding ItemsCollection}" SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
+0

「Mode = TwoWay」が必要ですか?ビューモデルコンストラクタでデフォルト値を設定しようとしましたが、うまくいきました。しかしセッターの中にセットするのは失敗している。 –

+0

@FaisalHafeezはい、ViewとViewModelのプロパティを変更していますので、 –

関連する問題