2012-02-06 5 views
1

からラベルを更新:私は私の質問/問題に入る前に、ここでは自分のアプリケーションの基本的な構造であるネストされたビューモデルのプロパティ

(この場合はメインビュー)私のMainWindow.xamlでは、私が持っていますラベル(私はのTextBlockにこれを変更する必要があり実現が、それは別の問題である):

<Label Name="StatusLabel" Content="{Binding Path=Status}"/> 

それはViewModelに(MainWindowViewModel)に対応していますが、別のViewModel(SiteListViewModel)とStatusプロパティが含まれています

public class MainWindowViewModel : ViewModelBase 
{ 
    public SiteListViewModel SiteList { get; set; } 
    public String Status 
    { 
     get { return SiteList.Status; } 
    } 
} 

あなたが見ることができるように、MainWindowViewModelのStatusプロパティは、そのように定義されてSiteListViewModelインスタンスStatusプロパティを返します:

public class SiteListViewModel : ViewModelBase 
{ 
    private string status; 
    public String Status 
    { 
     get { return this.status; } 
     set 
     { 
      this.status = value; 
      base.OnPropertyChanged("Status"); 
     } 
    } 
} 

SiteListViewModelのStatusプロパティは、何にとして通知ユーザーを維持するために非同期プロセスの間、様々な場所で更新され、続行中です。 MainWindowViewModelとSiteListViewModelの両方がINotifyPropertyChangedの実装をViewModelBaseから継承し、

Status = String.Format(Properties.Resources.SiteListViewModel_Status_LoadingJobs, count + 1, totalSites); 

もう一つの重要な注意:これは、のような単純な代入呼び出しで行われます。

ラベルが更新されません。実際の質問/問題のために今

。私が変更された場合

しかし、これにビューの結合:それは正常に動作します

<Label Name="StatusLabel" Content="{Binding Path=SiteList.Status}"/> 

。これは、私がMainWindowViewModelレベルで何かを見逃していることを示しているようです。私はそれをそのまま残すことができますが、それは私がやりたいことではない子ビューモデルの構造に到達します。

誰かが間違っていることを指摘できますか?

答えて

3

もちろん更新されません。バインディングシステムは、そのプロパティを所有する型でバインドしたプロパティのイベントをリッスンするようリッスンします。通知は一切発生しません。

あなたは、ネストされたVMの通知を転送できます。

OnPropertyChangedPropertyChangedを高めるための方法である
public MainWindowViewModel 
{ 
    SiteList.PropertyChanged += (s,e) 
     => if (e.PropertyName == "Status") OnPropertyChanged("Status"); 
} 

。あなたのVMのベースクラスは、そのようなものを持っている必要があります。

プロパティを削除することをお勧めします。SiteListを直接バインドすることができます(そのプロパティは、その設定者の変更通知を発行する必要があります)。また、ハンドラを古いインスタンスから切り離して、SiteListが変更されたときはいつでも新しいインスタンスに再接続する必要があります(セッタでも実行できます)。

+0

私はそれを行うことでカプセル化を壊しています。私は、PropertyChangedイベントがどのように処理されるかをよく理解していなかったと思います。 XAML/UIレベルで「親」プロパティにバインドされている限り、イベントがどのレベルで発生しても問題ではないと考えました。 –

+0

+1これを私の「未回答の質問」リストから取り除く。そして、あなたが同じことを同じ時刻にしたのと同じことをあなたが答えたからです:) – Rachel

0

何かがINotifyPropertyChangedを実装しているという理由だけで、プロパティがいつ変更されるかを自動的に知るわけではありません。あなたのコードでPropertyChangedイベントを発生させる必要があります。

例では、SiteListViewMode.PropertyChangedに登録し、ステータスが変更されたときにStatusの通知をPropertyChangedにすることで完了します。

public class MainWindowViewModel : ViewModelBase 
{ 
    public SiteListViewModel SiteList { get; set; } 
    public String Status 
    { 
     get { return SiteList.Status; } 
    } 

    public MainWindowViewModel() 
    { 
     // Of course, verify property isn't null first. 
     // Also, it's probably best to attach this in the setter 
     // so you can unhook the event from old items too 
     SiteList.PropertyChanged += SiteList_PropertyChanged; 
    } 

    void SiteList_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "Status") 
      RaisePropertyChanged("Status"); 
    } 
} 
0

MainWindowDataContextMainWindowViewModelですので。 LabelDataContexトンもMainWindowViewModelあるので

Labelはその後、同じDataContextを "継承" します。このため、SiteList.Statusを実行する必要があります。私は `SiteList.Status`(私はポストの終わり近くにそれを言った)に直接結合するが、それはのように感じているならば、それは動作します知っている(あなたがMainWindowViewModelPropertyChangedを上げるが、SiteListViewModelしているしていないので。)

+0

これはここでのポイントではなく、 'Status'もMainWindowViewModel上に存在します。 –

+0

right-o。ある構文がなぜ機能するのか、他の構文は機能しないのかを説明するマイナーアップデート。 –

関連する問題