2011-08-01 18 views
0

WPFのデータバインディングに問題があります。問題が非常に微妙であることが懸念されるため、私の説明では明確になることを願っています。WPFデータバインディング:項目の変更はどのように検出されますか?

私は本質的に、それぞれが相互に連結された複数のComboBoxを持つWPF UserControlを持っています。つまり、最初のコンボボックスにはいくつかの要素があり、ユーザーが選択して項目を選択すると、2番目のコンボボックスは前の選択に基づいた要素で満たされます。 すべてのコンボボックスは、UpdateSourceTrigger = LostFocusとバインドされています。

コンボのItemsSourceプロパティのコードは次のようになります。

private ICollectionView allTicketTypesView; 
    public IEnumerable<TicketTypeBase> AllTicketTypes 
    { 
     get { return this.allTicketTypesView.SourceCollection.Cast<TicketTypeBase>(); } 
     private set 
     { 
      IEnumerable<TicketTypeBase> enumerable = value ?? new TicketTypeBase[0]; 
      ObservableCollection<TicketTypeBase> source = new ObservableCollection<TicketTypeBase>(enumerable); 
      this.allTicketTypesView = CollectionViewSource.GetDefaultView(source); 
      this.OnPropertyChanged("AllTicketTypes"); 
     } 
    } 

コンボのSelectedItemプロパティのコードは、このコードのようになります。

private TicketTypeBase ticketType; 
public TicketTypeBase TicketType 
{ 
    get { return this.ticketType; } 
    set 
    { 
     this.ticketType = value; 
     this.OnPropertyChanged("TicketType"); 
     this.UpdateConcessions(); 
    } 
}  

私が経験しています微妙な問題: キーボードやマウスでコンボを動かすと、実際にはリストの項目を変更しないとpropertychangedが呼び出されることがよくあります。 私は、コンボが要素で満たされ、項目が選択されていることを意味します。キーボードでコンボを移動すると、propertychangedがトリガーされます(他のコンボが更新されます。同じ。 文字列のリスト(これはEquals/GetHashCode実装でエラーがないと仮定します)にバインドされたコンボボックスでこの動作が確認され、この動作は初めての場合を除き毎回発生します。

私はこれでコード修正しました:

private string category; 
    public string Category 
    { 
     get { return this.category; } 
     set 
     { 
      bool actuallyChanged = !String.Equals(this.category, value); 
      this.category = value; 
      this.OnPropertyChanged("Category"); 

      if (!actuallyChanged) 
      { 
       string format = String.Format("Category '{0}' isn't changed actually", value); 
       Trace.WriteLine(format); 
      } 
      else this.UpdateTicketTypes(): 
     } 
    } 

をしかし、もちろん、私はセッターにロジックを追加し、このコードを好きではありません。

この現象を回避する方法についてのご意見はありますか? 私は明確になることを望み、誰かがはっきり理解できない場合、私は自分の問題をより良く説明する準備ができています。

答えて

1

プロパティセッターで使用される値が実際の値と実際に異なるかどうかをモデルがチェックするのは無理がありません。しかし、より標準的な実装は次のようになります:

private string category; 
public string Category 
{ 
    get { return this.category; } 
    set 
    { 
     // check this is a new value 
     if(Object.Equals(this.category, value)) 
      return; 

     // set the value 
     this.category = value; 
     // raise change notification 
     this.OnPropertyChanged("Category"); 
     // compute related changes 
     this.UpdateTicketTypes(): 
    } 
} 
+0

返答ありがとうございます:しかし、初めてこの動作が起こると毎回私は狂気になります:-) –

0

SelectedItemの代わりにSelectedValueバインディングを実装できますか? SelectedValue(int、string、boolなどの値型の場合)は、キーボードやマウスのフォーカス時にリフレッシュしません。また、ItemsSource(CollectionView)が変更されても、値の型として発生しないソースまたはモデルの変更通知は変更されません参照により。

+0

は何も変わっていませんが、多分私はSelectedItem/SelectedValueの違い –