实验6—— 实现ViewModel

424 篇文章 1 订阅

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


namespace MvcAppLesson2.ViewModels
{
    public class EmployeeViewModel
    {
        public string EmployeeName { get; set; }
        public string Salary { get; set; }
        public string SalaryColor { get; set; }
        public string UserName{get;set;}
    }
}


       public ActionResult MyViewModel()
         {
             Employee emp = new Employee();
             emp.FirstName = "Sukesh";
             emp.LastName="Marla";
             emp.Salary = 20000;
          
             EmployeeViewModel vmEmp = new EmployeeViewModel();
             vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName;
             vmEmp.Salary = emp.Salary.ToString("C");
             if(emp.Salary>15000)
             {
                 vmEmp.SalaryColor="yellow";
             }
             else
             {
                 vmEmp.SalaryColor = "green";
             }


             vmEmp.UserName = "Admin";
          
             return View("StrongViewModel", vmEmp);
         }


  @using MvcAppLesson2.ViewModels
  @model EmployeeViewModel


@{
    Layout = null;
}


<!DOCTYPE html>


<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>StrongViewModel</title>
</head>
<body>
    <div>
       使用以下脚本代替View部分的内容 
    </div>
    Hello @Model.UserName <br />
    <hr />
    <div>
    <b>Employee Details</b><br />
        Employee Name : @Model.EmployeeName <br />
    <span style="background-color:@Model.SalaryColor">
            Employee Salary: @Model.Salary
    </span>
    </div>


</body>
</html>

理解ASP.NET MVC 中的View Model

实验5中已经违反了MVC的基本准则。根据MVC,V是View纯UI,不包含任何逻辑层。而我们在实验5中以下三点违反了MVC的体系架构规则。

1. 附加姓和名显示全名——逻辑层

2. 使用货币显示工资——逻辑层

3. 使用不同的颜色表示工资值,使用简单的逻辑改变了HTML元素的外观。——逻辑层

ViewModel 解决方法

ViewModel是ASP.NET MVC应用中隐式声明的层。它是用于维护Model与View之间数据传递的,是View的数据容器。

Model 和 ViewModel 的区别

Model是业务相关数据,是根据业务和数据结构创建的。ViewModel是视图相关的数据。是根据View创建的。

具体的工作原理

  1. Controller 处理用户交互逻辑或简单的判断。处理用户需求
  2. Controller 获取一个或多个Model数据
  3. Controller 决策哪个View最符合用户的请求
  4. Controller 将根据Model数据和View需求创建并且初始化ViewModel对象。
  5. Controller 将ViewModel数据以ViewData或ViewBag或强类型View等对象传递到View中。
  6. Controller 返回View。

View 与 ViewModel 之间是如何关联的?

View将变成ViewModel的强类型View。

Model和 ViewModel 是如何关联的?

Model和ViewModel 是互相独立的,Controller将根据Model对象创建并初始化ViewModel对象。

接下来我们来看实验6:

实验6—— 实现ViewModel

1. 新建文件夹

在项目中创建新文件夹并命名为ViewModels。

2. 新建EmployeeViewModel

为了达到实验目的,首先列出我们的实验需求:

1. 名和姓应该合并显示。

2. 使用货币显示数量

3. 薪资以不同的颜色来显示

4. 当前登录用户也需要在View中显示。

在ViewModels类中,创建新类并命名为EmployeeViewModel,如下所示:

   1:  public class EmployeeViewModel
   2:  {
   3:      public string EmployeeName { get; set; }
   4:      public string Salary { get; set; }
   5:      public string SalaryColor { get; set; }
   6:      public string UserName{get;set;}
   7:  }
注意,姓和名应该使用EmployeeName这一个属性。而Salary属性的数据类型是字符串,且有两个新的属性添加称为SalaryColor和UserName。
3. View中使用ViewModel

实验五中已经创建了View的强类型Employee。将它改为 EmployeeViewModel

   1:  @using WebApplication1.ViewModels
   2:  @model EmployeeViewModel
 

4. 在View中显示数据

使用以下脚本代替View部分的内容

   1:  Hello @Model.UserName
   2:  <hr />
   3:  <div>
   4:  <b>Employee Details</b><br />
   5:      Employee Name : @Model.EmployeeName <br />
   6:  <span style="background-color:@Model.SalaryColor">
   7:          Employee Salary: @Model.Salary
   8:  </span>
   9:  </div>

5. 新建并传递ViewModel

在GetView方法中,获取Model数据并且将强制转换为ViewModel对象。

   1:  public ActionResult GetView()
   2:  {
   3:      Employee emp = new Employee();
   4:      emp.FirstName = "Sukesh";
   5:      emp.LastName="Marla";
   6:      emp.Salary = 20000;
   7:   
   8:      EmployeeViewModel vmEmp = new EmployeeViewModel();
   9:      vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName;
  10:      vmEmp.Salary = emp.Salary.ToString("C");
  11:      if(emp.Salary>15000)
  12:      {
  13:          vmEmp.SalaryColor="yellow";
  14:      }
  15:      else
  16:      {
  17:          vmEmp.SalaryColor = "green";
  18:      }
  19:   
  20:  vmEmp.UserName = "Admin"
  21:   
  22:      return View("MyView", vmEmp);
  23:  }

6. 测试输出

clip_image006

尽管运行结果类似,但是View中不包含任何业务逻辑。

关于实验6

是否意味着,每个Model都有一个ViewModel?

每个View有其对应的ViewModel。

Model与ViewModel之间存在关联是否是好的实现方法?

最好的是Model与ViewModel之间相互独立。

需要每次都创建ViewModel吗?假如View不包含任何呈现逻辑只显示Model数据的情况下还需要创建ViewModel吗?

建议是每次都创建ViewModel,每个View都应该有对应的ViewModel,尽管ViewModel包含与Model中相同的属性。

假定一个View不包含任何呈现逻辑,只显示Model数据,我们不创建ViewModel会发生什么?

无法满足未来的需求,如果未来需要添加新数据,我们需要从头开始创建全新的UI,所以如果我们保持规定,从开始创建ViewModel,就不会发生这种情况。在本实例中,初始阶段的ViewModel将与Model几乎完全相同。



在多个Fragment之间共享ViewModel,可以使用以下步骤: 1. 创建一个ViewModel类,该类包含需要共享的数据和方法。 ```java public class SharedViewModel extends ViewModel { private MutableLiveData<String> selected = new MutableLiveData<String>(); public void select(String item) { selected.setValue(item); } public LiveData<String> getSelected() { return selected; } } ``` 2. 在需要共享ViewModel的Fragment中,通过ViewModelProvider获取ViewModel实例。 ```java public class Fragment1 extends Fragment { private SharedViewModel model; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); } // ... } ``` 3. 在其他需要访问ViewModel的Fragment中,也通过ViewModelProvider获取同一个ViewModel实例。 ```java public class Fragment2 extends Fragment { private SharedViewModel model; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); } // ... } ``` 4. 在Fragment中使用ViewModel中的数据和方法。这样就可以在多个Fragment之间共享ViewModel了。 ```java public class Fragment1 extends Fragment { private SharedViewModel model; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1, container, false); Button button = view.findViewById(R.id.button); final EditText editText = view.findViewById(R.id.editText); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { model.select(editText.getText().toString()); } }); return view; } } public class Fragment2 extends Fragment { private SharedViewModel model; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment2, container, false); final TextView textView = view.findViewById(R.id.textView); model.getSelected().observe(getViewLifecycleOwner(), new Observer<String>() { @Override public void onChanged(String item) { textView.setText(item); } }); return view; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值