2013-04-18 33 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