2013-04-18 51 views
1

我有點試驗MVVM再次,我目前遇到兩個問題與我的代碼。
首先讓我解釋一下代碼結構:INotifyPropertyChanged在單身人士和綁定到WPF元素

我有這樣一個類(簡化當然):

public abstract class NavigationServiceBase : NotifyPropertyChangedBase, INavigationService 
{ 
    private IView _currentView; 
    public IView CurrentView 
    { 
     get { return _currentView; } 
     protected set 
     { 
      _currentView = value; 
      OnPropertyChanged("CurrentView"); 
     } 
    } 

    public virtual void DoSomethingFancy() 
    { 
     CurrentView = ...; // here I expect it to fire OnPropertyChanged and notify my View 
    } 
} 

而且單從這個基類繼承:

public class NavigationService : NavigationServiceBase 
{ 
    private static readonly INavigationService _instance = new NavigationService(); 
    public static INavigationService Instance { get { return _instance; } } 

    ... 
} 

視圖模型:

private INavigationService _navigationService; 

public IView CurrentView { get { return _navigationService.CurrentView; } } 
public ICommand NavigateCommand { get; private set; } 

public MainWindowViewModel() 
{ 
    _navigationService = NavigationService.Instance; 
    NavigateCommand = new RelayCommand(param => Navigate(param)); 
} 

private void Navigate(object requestedPage) 
{ 
    _navigationService.Navigate((string)requestedPage); 
    //OnPropertyChanged("CurrentView"); // this works , but... 
} 

現在問題:
1.)我正在編輯Visual Studio 2012 Express中的XAML。它似乎有效,但我收到一條警告消息:Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information.它顯示在我聲明資源綁定ViewModel的部分。這是什麼意思?如果我擺脫了單身人士,消息就消失了。項目編譯和運行都很好。

2.)看來我的OnPropertyChanged(「CurrentView」)沒有觸發或什麼,因爲我必須從ViewModel本身手動調用此方法。如果我從基類或繼承單例中嘗試它,它不起作用。 (綁定只是忽略新的值)。如果我在處理命令時手動執行此操作,它將起作用。是的,這只是一個額外的代碼行,但我想知道,有沒有一種方法可以讓它工作而不會像這樣「欺騙」?

回答

2

的問題是,要綁定在你的ViewModel屬性:

public IView CurrentView { get { return _navigationService.CurrentView; } } 

NatigationService是提高PropertyChanged,但這種情況發生在_navigationService,而不是在視圖模型本身,所以視圖不會看到事件。

有兩種常用的選項 -

你可以聽你的導航服務的PropertyChanged事件,如果需要處理提高在本地:

_navigationService = NavigationService.Instance; 
_navigationService.PropertyChanged += (o,e) => 
{ 
    // When navigation raises prop changed for this property, raise it too 
    if (e.PropertyName == "CurrentView") 
    OnPropertyChanged("CurrentView"); 
}; 
NavigateCommand = new RelayCommand(param => Navigate(param)); 

的另一種方法是公開服務,並直接綁定到它:

public INavigationService Navigation { get { return _navigationService; } } 

然後,在你看來,綁定到內容服務,而不是本地屬性的內部:

<ContentPresenter Content="{Binding Navigation.CurrentView}" /> 
+0

啊,我明白了。有道理:)謝謝。我自己找出了第一個「問題」的原因,顯然這只是一件愚蠢的事情。我試圖在構造函數中進行一些反射,試圖檢查當前程序集,這在設計應用程序時明顯失敗。 – walther