访问 ContentControl 的父视图模型中的属性

本文关键字:属性 模型 ContentControl 访问 视图 | 更新日期: 2023-09-27 18:34:18

我有我的MainWindow,它加载了新的UserControls,并且ViewModel进入了它的ContentControl,所以视图被切换了。

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

主窗口视图模型

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,它位于MainWindow 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 

编辑:这是我在主窗口视图模型中添加视图的地方

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();
        }
    }
}

访问 ContentControl 的父视图模型中的属性

您只需

要在ContentControl's任何子元素中使用Ancestor绑定:

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

如果Window MainWindowViewModelDataContext.

我会选择ViewModel到ViewModel通信的事件,我更喜欢IEventAggregator,作为Microsoft的PubSub nuget包提供,但有很多选择(如果你愿意,也可以自己动手)。

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

在您的 LoginViewModel 中,在用户登录后发布它:

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

使用 Prism 的 IEventAggregator,事件类很简单:

public class UserLoggedInEvent : PubSubEvent<User> {}

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