c# - 如何在不破坏 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);
}
}
}
解决方案
以纯粹的方式,没有指定的框架。
- 创建一个事件委托(或监听器接口),与视图模型相关联
- 在视图上注册事件处理程序
- 更改视图模型时触发事件
喜欢这个
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();
}
}
推荐阅读
- excel - 数字格式在 VBA 中无法正常工作
- node.js - 生产服务器上 docker 环境中的 Node.js 内存泄漏
- c# - 如何实例化一个类?
- c++ - 有人可以解释 3D 形状中的 Z 值是多少吗?
- firebase - 如何在颤振飞镖中每 20 秒显示一次插页式广告
- ibm-cloud - IBM Cloud:无法访问 Ambari 控制台
- python - Python中时间序列的真实样本外预测
- javascript - ReferenceError:foundItems 未定义
- java - 使用 JAVA 获取 WebElement 在屏幕上的位置
- python-3.x - 使用 Python 3.7 云函数并行写入 Firestore