2011-08-09 25 views
1

問題は簡単です。私はオブジェクトのObservableCollectionにバインドされたツリービューを持っており、それらのオブジェクトはすべて独自のObservableCollectionを持っています。私のページ上の他の基準のユーザ選択に基づいて、チェックされるチェックボックスを動的に設定したい。 残念ながら、対応するboolプロパティをIsCheckedに変更した後、私のチェックボックスはIsCheckedステータスを更新できません。チェックボックスはノードが最初に展開されたときに正しい状態になりますが、その後は更新が停止します。私は、オブジェクトが初めて実際に表示されるまで、オブジェクトが作成/評価されないことを意味します。バインドされたプロパティが変更された後にツリービューのチェックボックスが更新されない(SL4)

データの構造は、Silverlightのである - > ViewModelに - > StoreGroups LocalStoreGroupsののObservableCollection - > StoreGroupは、私がthis.PropertyChangedに添付何のハンドラが存在しないことに気づいた、と疑問に思ってデバッグを介して店舗店舗のObservableCollection

を持っていますこれが問題ならば?

ツリービューコントロール:私のプロジェクトで

<controls:TreeView ItemsSource="{Binding LocalStoreGroups}" ItemTemplate="{StaticResource TreeviewStoreGroupTemplate}" /> 

私は、次のHeirarchalDataTemplatesとツリービューを使用します。

<UserControl.Resources> 
    <sdk:HierarchicalDataTemplate x:Key="TreeviewStoreTemplate"> 
      <CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding DTO.Name}" /> 
    </sdk:HierarchicalDataTemplate> 
    <sdk:HierarchicalDataTemplate x:Key="TreeviewStoreGroupTemplate" ItemsSource="{Binding Stores}" ItemTemplate="{StaticResource TreeviewStoreTemplate}"> 
      <CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding DTO.Name}" /> 
    </sdk:HierarchicalDataTemplate> 
</UserControl.Resources> 

IsSelectedプロパティのコード(StoreGroupオブジェクトとストアオブジェクトの両方がこれを持っていますプロパティ:

private bool _IsSelected; 
    public bool IsSelected 
    { 
     get { return _IsSelected; } 
     set 
     { 
      _IsSelected = value; 
      OnPropertyChanged("IsSelected"); 
     } 
    } 
protected void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler temp = this.PropertyChanged; 
     if (null != temp) 
      temp(this, e); 
    } 

変更するコードIsSelected

foreach (Store s in LocalStoreGroups.SelectMany(sg => sg.Stores)) 
     { 
      s.IsSelected = false; 
     } 

     foreach (StoreLink link in links) 
     { 
      Store targetStore = (from s in LocalStoreGroups.SelectMany(sg => sg.Stores) where s.DTO.ID == link.DTO.StoreID select s).FirstOrDefault(); 
      targetStore.IsSelected = true; 
     } 
+0

値を設定すると、これはバックグラウンドスレッドで発生しますか? – thumbmunkeys

+0

いいえ、下部のコード(IsSelectedを変更するコード)は、UIスレッドで次のメソッドを使用して呼び出されます。DispatcherHelper.CheckBeginInvokeOnUI(...)from Mvvmlight。 –

+0

'OnPropertyChanged'メソッドは、文字列を受け入れることはできませんが、文字列を渡してもどうですか? – thumbmunkeys

答えて

0

、ギブアウェイここでは誰もがPropertyChangedイベントに加入しなかったことをされている必要があります。私はPropertyChangedイベントを実装しましたが、クラスに実際にINotifyPropertyChangedインターフェイスを与えるのを忘れていました。

2

ロードイベントに応答してプロパティを更新しているようです。プロパティを更新すると、UIスレッドに参加していない可能性があります。変更がUIスレッドで発生しない限り、表示は更新されません。

バインドされたプロパティとプロパティ(コレクションであり、観察可能なコレクション内の子ではない)の場合は、UIスレッド上にある必要があるOnPropertyChangedのみです。プロパティは以前に変更できますが、UIはOnPropertyChangedが呼び出されるまでバインディングを変更しません。

私たちが作成したViewModelBaseは、以下のようにヘルパーSendPropertyChangedを実装しています(Cross-Threadingについて心配する必要はありません)。

すべてのnotifyプロパティは、OnPropertyChangedを直接呼び出すのではなく、それを呼び出します。あなたはUIスレッド上で任意のコードを実行することができますので、それはまた、一般的に有用なOnUiThread方法を公開し

:とにかく

protected delegate void OnUiThreadDelegate(); 

public event PropertyChangedEventHandler PropertyChanged; 

public void SendPropertyChanged(string propertyName) 
{ 
    if (this.PropertyChanged != null) 
    { 
     this.OnUiThread(() => this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName))); 
    } 
} 

protected void OnUiThread(OnUiThreadDelegate onUiThreadDelegate) 
{ 
    if (Deployment.Current.Dispatcher.CheckAccess()) 
    { 
     onUiThreadDelegate(); 
    } 
    else 
    { 
     Deployment.Current.Dispatcher.BeginInvoke(onUiThreadDelegate); 
    } 
} 
+0

Visual Studioでブレークポイントを調べると、メインスレッドで更新コードが呼び出されていることが確認できます。また、MVVMLightフレームワークを使用しています。MVVMLightフレームワークは、あなたが提案していることを行う方法を公開しています(ただし、あなたの解決策はちょっとしたソリューションのようです)。最後に、プロパティ変更イベントは、変更を通知しようとしているオブジェクトのthis.PropertyChanged = nullとしてスローされません。観察可能なコレクション内のオブジェクトの子である可能性がありますか? –

+0

+1私は 'OnUiThread'が好きですから。 – AnthonyWJones

関連する問題