2016-02-11 68 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