首页 > 解决方案 > 如何在不破坏 MVVM 的情况下从 ViewModel 通知 View?

问题描述

我最近开始在学校尝试 MVVM 模式,想知道最好的方法(如果有的话)是从 ViewModel 通知 View,让视图知道在不破坏 MVVM 的情况下运行方法?基本上让视图知道某事是否成功,例如登录尝试或尝试连接到数据库?

一个例子可能是一个登录页面,只有当登录成功时,主窗口才应该将内容更改为新页面,如果没有,应该显示一个消息框

编辑:

我正在使用.NET

到目前为止我已经尝试过:

看法:

<Page
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:View.Pages" xmlns:ViewModels="clr-namespace:ViewModel.ViewModels;assembly=ViewModel" x:Class="View.Pages.Start_Page"
      mc:Ignorable="d" 
      d:DesignHeight="720" d:DesignWidth="1280"
      Title="Start_Page">

    <Page.DataContext>
        <ViewModels:Start_Page_ViewModel/>
    </Page.DataContext>

背后的代码:

public Start_Page()
        {
            InitializeComponent();

            Start_Page_ViewModel currentDataContext = DataContext as Start_Page_ViewModel;

            currentDataContext.CurrentUserIDGotten += GoToMenu;
        }

        private void GoToMenu(int result)
        {
            if (result == -1)
            {
                MessageBox.Show("User credentials incorrect");
            }
            else if (result == -2)
            {
                MessageBox.Show("Connection failed");
            }
            else
            {
                Application.Current.MainWindow.Content = new Menu_Page();
            }
        }

视图模型:

public class Start_Page_ViewModel
    {

        private string userName;
        private string userPassword;

        public string UserName { get => userName; set => userName = value; }

        public string UserPassword { get => userPassword; set => userPassword = value; }

        private RelayCommand logIn;

        public RelayCommand LogIn => logIn;


        public delegate void CurrentUserIDGottenEventHandler(int result);
        public event CurrentUserIDGottenEventHandler CurrentUserIDGotten;

        public Start_Page_ViewModel()
        {
            logIn = new RelayCommand(LogInToProgram, CanLogIn);
        }

        public void LogInToProgram(object o)
        {
            PasswordBox passwordBox = o as PasswordBox;

            ViewModelController.Instance.CurrentUserID = Database_Controller.Instance.SignIn(userName, passwordBox.Password);

            OnUserIDGotten(ViewModelController.Instance.CurrentUserID);
        }

        public bool CanLogIn(object o)
        {
            if (userName != null)
            {
                return true;
            }
            return false;
        }

        protected virtual void OnUserIDGotten(int result)
        {
            if (CurrentUserIDGotten != null)
            {
                CurrentUserIDGotten(result);
            }
        }
    }

标签: c#mvvm

解决方案


以纯粹的方式,没有指定的框架。

  1. 创建一个事件委托(或监听器接口),与视图模型相关联
  2. 在视图上注册事件处理程序
  3. 更改视图模型时触发事件

喜欢这个

using System;

public class MainClass {
  public static void Main (string[] args) {
    ViewModel m = new ViewModel();
    View v = new View();
    v.Model = m;
    m.MakeSomeChange();
  }
}

public class View {
  private IViewModel _model;
  public IViewModel Model {
    get {
      return _model;
    }
    set {
      if(_model != null) {
        _model.OnChanged -= OnChanged;
      }
      if(value != null) {
        value.OnChanged += OnChanged;
      }
      _model = value;
    }
  }
  private void OnChanged(){
    //update view
    Console.WriteLine ("View Updated");
  }
}

public delegate void ViewChangeDelegate();

public interface IViewModel {
  event ViewChangeDelegate OnChanged;
}

public class ViewModel: IViewModel {
  public event ViewChangeDelegate OnChanged;

  public void MakeSomeChange() {
    //make some change in the view Model
    OnChanged.Invoke();
  }
}

推荐阅读