【MVVM】WPF
程序员文章站
2024-02-02 11:17:04
...
一、新建WPF Demo
添加一个Student类,代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;// INotifyPropertyChanged
namespace MVVMDemo
{
public class Student: INotifyPropertyChanged
{
string firstName;
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
string lastName;
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
OnPropertyChanged("LastName");
}
}
public Student(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
修改MainWindow.xaml,代码如下
<Window x:Class="MVVMDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVMDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid x:Name="gridLayout">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<TextBlock Text="FirstName:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Path=FirstName,Mode=TwoWay}" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBlock Text="LastName:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox Text="{Binding Path=LastName,Mode=TwoWay}" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Button x:Name="BtnView" Content="I am View" Grid.Row="2" Grid.Column="0" Width="150" Height="50" VerticalAlignment="Center" HorizontalAlignment="Right"/>
</Grid>
</Window>
MainWindow视图
在MainWindow.xaml.cs添加以下代码
public MainWindow()
{
InitializeComponent();
Student student = new Student("Wang","WenSong");
gridLayout.DataContext = student;
BtnView.Click += new RoutedEventHandler(delegate (object sender, RoutedEventArgs e)
{
student.FirstName = "BBK工作室";
student.LastName = "www.bigbearking.com";
});
}
点击“I am View” Button按钮,运行程序,如下图
新建一个超类
NotificationObject.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
namespace MVVMDemo
{
public abstract class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void RaisePropertyChanged(params string[] propertyNames)
{
if (propertyNames == null) throw new ArgumentNullException("propertyNames");
foreach (var name in propertyNames)
{
this.RaisePropertyChanged(name);
}
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
var propertyName = ExtractPropertyName(propertyExpression);
this.RaisePropertyChanged(propertyName);
}
public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
{
throw new ArgumentNullException("propertyExpression");
}
var memberExpression = propertyExpression.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException("PropertySupport_NotMemberAccessExpression_Exception", "propertyExpression");
}
var property = memberExpression.Member as PropertyInfo;
if (property == null)
{
throw new ArgumentException("PropertySupport_ExpressionNotProperty_Exception", "propertyExpression");
}
var getMethod = property.GetGetMethod(true);
if (getMethod.IsStatic)
{
throw new ArgumentException("PropertySupport_StaticExpression_Exception", "propertyExpression");
}
return memberExpression.Member.Name;
}
}
}
修改student.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;// INotifyPropertyChanged
namespace MVVMDemo
{
public class Student: NotificationObject
{
string firstName;
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
//OnPropertyChanged("FirstName");
this.RaisePropertyChanged("LastName");
}
}
string lastName;
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
//OnPropertyChanged("LastName");
this.RaisePropertyChanged("LastName");
}
}
public Student(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
二、建立MVVM的各个部分
在WPF工程上建立 Model、View、ViewModel 三个文件夹
1. 将Student.cs移到Model文件夹内,并修改Student.cs里的代码,修改后的Student.cs内容如***意命名空间的变化)
Student.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMDemo.Model
{
public class Student
{
string firstName;
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}
string lastName;
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
}
}
public Student()
{
//模拟获取数据
//这里为什么会有模拟数据一说呢?我是这样认为的,有时候类的属性会存在数据库或者本地文件系统等上面,
//我们需要读取操作将这些数据加载到咱们定义的类里。
Mock();
}
public void Mock()
{
FirstName = "firstName:" + DateTime.Now.ToString();
LastName = "lastName:" + DateTime.Now.ToString();
}
}
}
工程结构图
2.在ViewModel文件夹右击添加一个StudentViewModel类
StudentViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MVVMDemo.Model;
namespace MVVMDemo.ViewModel
{
public class StudentViewModel:NotificationObject
{
private Student student;
public Student Student
{
get
{
return this.student;
}
set
{
this.student = value;
//下面这一句话的用法以后再拿出一章具体介绍
this.RaisePropertyChanged(() => this.student);
}
}
public StudentViewModel()
{
student = new Student();
}
}
}
工程结构图
3.在View文件夹下添加一个用户控件,命名为StudentView。
StudentView.xaml
<UserControl x:Class="MVVMDemo.View.StudentView"
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:MVVMDemo.View"
xmlns:vm="clr-namespace:MVVMDemo.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid x:Name="gridLayout">
<Grid.DataContext>
<vm:StudentViewModel />
</Grid.DataContext>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*" />
<RowDefinition Height="5*" />
<RowDefinition Height="5*" />
<RowDefinition Height="5*" />
</Grid.RowDefinitions>
<TextBlock Text="FirstName:" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Path=Student.FirstName,Mode=Default}" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBlock Text="LastName:" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox Text="{Binding Path=Student.LastName,Mode=TwoWay}" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Button x:Name="BtnView" Content="I am View" Grid.Row="2" Grid.Column="0" Width="150" Height="50" VerticalAlignment="Center" HorizontalAlignment="Right"/>
</Grid>
</UserControl>
工程结构图
然后在MainWindow里需要引用这个控件,修改MainWindow.xaml的代码
<Window x:Class="MVVMDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:MVVMDemo.View"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="gridLayout">
<view:StudentView />
</Grid>
</Window>
再将MainWindow.cs里之前添加的代码删掉,修改后的内容如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MVVMDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
运行程序,效果图如下
上一篇: vue之mvvm原理解析
下一篇: Vue响应式原理与模拟