2016-02-11 50 views
0

我有我的MainWindow加载新的UserControls和ViewModel到它的ContentControl,所以视图切换。访问属性在ContentControl的父视图模型

但是,我需要从ContentControl中的ViewModel访问我的MainWindow ViewModel中的属性。

MainWindowViewModel

namespace PhotoManagement 
{ 
    public class MainWindowViewModel : NotifyUIBase 
    { 
     public ObservableCollection<ViewVM> Views { get; set; } 

     private ObservableCollection<Logged> loggedUsers; 
     public ObservableCollection<Logged> LoggedUsers 
     { 
      get 
      { 
       return loggedUsers; 
      } 
      set 
      { 
       loggedUsers.Add(value[0]); 

       //There is a user logged in, switch to home and display menu 
       if (loggedUsers.Count > 0) 
       { 
        //Display menu, switch Windows 
        MessageBox.Show("Someone is logged in!"); 
       } 
       else 
       { 
        MessageBox.Show("No-one is logged in!"); 
       } 
      } 
     } 

下面你可以看到LoginViewModel这是在主窗口ContentControl中,我已经加入其中,我想要这个新的用户添加到的ObservableCollection评论。

#region Login Methods 
     private LoginVM loginVM; 
     public LoginVM LoginVM 
     { 
      get 
      { 
       return loginVM; 
      } 
      set 
      { 
       loginVM = value; 
       editEntity = editVM.TheEntity; 
       RaisePropertyChanged(); 
      } 
     } 
     protected override void DoLogin() 
     { 
      //Check if email exists 
      var exist = db.Users.Count(a => a.Email == LoginVM.TheEntity.Email); 
      if (exist != 0) 
      { 
       //Fecth user details 
       var query = db.Users.First(a => a.Email == LoginVM.TheEntity.Email); 
       if (Common.Security.HashGenerator.CalculateHash(LoginVM.TheEntity.ClearPassword, query.Salt) == query.Hash) 
       { 
        //Password is correct 
        MessageBox.Show("Details correct!"); 

        //Set properties 
        LoginVM.TheEntity.FirstName = query.FirstName; 
        LoginVM.TheEntity.LastName = query.LastName; 
        LoginVM.TheEntity.UID = query.UID; 

        //Add the LoginVM to LoggedUsers 

编辑: 这是我补充的意见,MainWindowViewModel

namespace PhotoManagement 
{ 
    public class MainWindowViewModel : NotifyUIBase 
    { 
     public ObservableCollection<ViewVM> Views { get; set; } 

     private ObservableCollection<Logged> loggedUsers; 
     public ObservableCollection<Logged> LoggedUsers 
     { 
      get 
      { 
       return loggedUsers; 
      } 
      set 
      { 
       loggedUsers.Add(value[0]); 

       //There is a user logged in, switch to home and display menu 
       if (loggedUsers.Count > 0) 
       { 
        //Display menu, switch Windows 
        MessageBox.Show("Someone is logged in!"); 
       } 
       else 
       { 
        MessageBox.Show("No-one is logged in!"); 
       } 
      } 
     } 

     public string Version 
     { 
      get { return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); } 
     } 

     public MainWindowViewModel() 
     { 
      ObservableCollection<ViewVM> views = new ObservableCollection<ViewVM> 
      { 
       new ViewVM { IconGeometry=App.Current.Resources["home4"] as Geometry, ViewDisplay="Home", ViewType = typeof(LoginView), ViewModelType = typeof(LoginViewModel)}, 
       new ViewVM { IconGeometry=App.Current.Resources["instagram3"] as Geometry, ViewDisplay="Images", ViewType = typeof(LoginView), ViewModelType = typeof(LoginView)}, 
       new ViewVM { IconGeometry=App.Current.Resources["money674"] as Geometry, ViewDisplay="Sales", ViewType = typeof(LoginView), ViewModelType = typeof(LoginViewModel)}, 
       new ViewVM { IconGeometry=App.Current.Resources["printing1"] as Geometry, ViewDisplay="Print Queue", ViewType = typeof(LoginView), ViewModelType = typeof(LoginViewModel)}, 
       new ViewVM { IconGeometry=App.Current.Resources["cog2"] as Geometry, ViewDisplay="Settings", ViewType = typeof(IconLibaryView), ViewModelType = typeof(IconLibaryViewModel)}, 
       new ViewVM { IconGeometry=App.Current.Resources["upload40"] as Geometry, ViewDisplay="Upload", ViewType = typeof(IconLibaryView), ViewModelType = typeof(IconLibaryViewModel)} 
      }; 
      Views = views; 
      RaisePropertyChanged("Views"); 
      views[0].NavigateExecute(); 
     } 
    } 
} 
+1

当'MainWindowViewModel'创建'LoginVM'添加到'Views'集合时,它应该给它一个属性或委托,以便它可以设置当前登录的用户。如果'MainWindowViewModel'和'LoginVM'完全不连接,则可以使用消息传递系统,例如MVVM Light的'Messenger'或Microsoft Prism的'EventAggregator'。 – Rachel

+0

@Rachel,我在添加视图的地方添加了代码,你能否解释一下你的意思,当你说它应该给它一个属性时,我可以设置用户。以前没有尝试过使用'Messenger',必须仔细查看它。 –

+1

在您的ViewModel中加载UserControls? Noooooooooooooooo0ope。您应该使用绑定到您的视图模型和模型的ContentControls和ItemsControls,以及包含与每个模型匹配的UI的DataTemplates。这不是MVVM,它是旧代码隐藏和MVVM之间的一种混合。 – Will

回答

0

我会与视图模型到视图模型通信事件去了,我更喜欢IEventAggregator,可作为PubSub nuget包来自微软,但有很多可供选择的(或者如果你愿意的话可以推出自己的产品)。

public MainViewModel() { 
    Aggregator.GetEvent<UserLoggedInEvent>().Subscribe(user => ...do your magic); 
} 

而在你LoginViewModel,发布用户在登录后:

public DoLogin() { 
    ... do other stuff here... 
    Aggregator.GetEvent<UserLoggedInEvent>().Publish(userDetails); 
} 

从棱镜使用IEventAggregator,事件类很简单:

public class UserLoggedInEvent : PubSubEvent<User> {} 

顺便说一句 - 一个MVVM或任何设计模式的主要目的是从业务代码抽象UI,所以如果你可以使用转换器或其他东西从你的VM中删除所有的App.Current.Resources的东西,那么你已经有了abs将它从WPF中移出(更容易移植到其他平台,如UWP)。

0

您只需使用Ancestor任何子元素ContentControl's内结合:

{Binding RelativeSource={RelativeSource AncestorType={x:Type Window},Path=DataContext.AnyPropertyOfMainWindowViewModel} 

如果WindowMainWindowViewModelDataContext