繁体   English   中英

INotifyPropertyChanged以单例形式并绑定到WPF元素

[英]INotifyPropertyChanged in singleton and binding to the WPF element

我再次尝试使用MVVM,目前我的代码遇到两个问题。
首先让我解释一下代码结构:

我有一个这样的课(当然是简化的):

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. Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information. 当我声明用于绑定ViewModel的资源时,它将在该部分中显示。 这是什么意思? 如果我摆脱了单例,消息就消失了。 无论哪种方式,项目都可以编译和运行。

2.)我的OnPropertyChanged(“ CurrentView”)似乎没有触发,因为我必须从ViewModel本身内部手动调用此方法。 如果我从基类或继承的单例中尝试它,它将无法正常工作。 (绑定只是忽略新值)。 如果我在执行命令时手动执行此操作,则它将起作用。 是的,这只是一行额外的代码,但是我想知道,是否有一种方法可以使它像这样“作弊”呢?

问题是您要绑定到ViewModel中的属性:

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

NatigationService正在引发PropertyChanged ,但这发生在_navigationService ,而不是在ViewModel本身中发生,因此View永远不会看到该事件。

有两个常见选项-

您可以在导航服务上侦听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}" />

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM