创建MVVM程序
MVVM即Model-View-ViewModel,是一种界面与业务逻辑相分离的一种架构,其中Model负责业务逻辑,View负责图形界面,二者通过ViewModel进行交互。微软官方的【CommunityToolkit】提供了Mvvm包,可用于生成MVVM程序。
本文将通过MVVM设计模式,创建一个左手和右手玩的小游戏,比手速

其运行逻辑是,左手按【A】,右手按【L】,快的加分,同时将对方的按钮置为灰色并禁用,只有当胜者按下按钮之后,败者的按钮才能继续使用,从而起到羞辱败者的目的。
新建一个WPF程序,右键单击解决方案资源管理器中的项目名称->管理NuGet包,搜索【CommunityToolkit.Mvvm】即可安装。
由于MVVM由三部分构成,因此创建三个文件夹【Models】、【Views】以及【ViewModels】来分别存放这三类代码。
作为入门程序,功能不宜复杂,故三个文件夹中分别只有一个文件
- Models
- Views
- MainView.xaml
- MainView.xaml.cs
- ViewModels
至此,框架已经搭好,接下来就是分别实现模型、界面以及交互了。
Model
这个手速测试程序的模型要求非常简单,只需一左一右两个计分的变量即可。
namespace SpeedMatch.Models;
public class SpeedCounter
{
public int LeftHits { get; set; }
public int RightHits { get; set; }
}
MainView
在Views文件夹中创建【MainView.xaml】文件,内容如下。
<UserControl x:Class="SpeedMatch.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Stats}" FontSize="20" Margin="0,0,0,20" HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal">
<Button Content="Left (A)" Width="100" Height="60" Margin="10"
Command="{Binding HitLeftCommand}" IsEnabled="{Binding LeftEnabled}">
</Button>
<Button Content="Right (L)" Width="100" Height="60" Margin="10"
Command="{Binding HitRightCommand}" IsEnabled="{Binding RightEnabled}">
</Button>
</StackPanel>
</StackPanel>
<UserControl.InputBindings>
<KeyBinding Key="A" Command="{Binding AddScoreCommand}" CommandParameter="A"/>
<KeyBinding Key="L" Command="{Binding AddScoreCommand}" CommandParameter="L"/>
</UserControl.InputBindings>
</UserControl>
和普通的WPF程序相比,【Command】是个新鲜玩意,其中【Left(A)】和【Right(L)】这两个按钮绑定了HitLeft和HitRight两个方法,Command为二者的后缀。绑定按键的AddScore同理,但该函数有输入参数,即【CommandParameter】。
此外,【IsEnabled】绑定的两个属性也颇有讲究,此二者也是MVVM转化而来,一会儿我们将看到二者在C#中的样子。
别忘了写与之配套的cs文件。
namespace SpeedMatch.Views
{
public partial class MainView : UserControl
{
public MainView() => InitializeComponent();
}
}
也别忘了将其加入到主窗口。
<Window x:Class="SpeedMatch.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:SpeedMatch"
xmlns:views="clr-namespace:SpeedMatch.Views"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<views:MainView/>
</Window>
MainViewModel
【MainViewModel】是模型和界面之间的桥梁,也是MVVM的关键工作,而这种沟通是通过类似ObservableProperty、RelayCommand这样的字段实现的。
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SpeedMatch.Models;
namespace SpeedMatch.ViewModels;
public partial class MainViewModel : ObservableObject
{
[ObservableProperty] private bool _leftEnabled = true;
[ObservableProperty] private bool _rightEnabled = true;
private readonly SpeedCounter _counter = new();
[ObservableProperty] private string _stats = "Left:0/ Right: 0";
[RelayCommand]
private void AddScore(String key)
{
if(!RightEnabled || !LeftEnabled)
return;
if (key == "A")
{
RightEnabled = false;
_counter.LeftHits++;
}
else if (key == "L")
{
LeftEnabled = false;
_counter.RightHits++;
}
Stats = $"Left:{_counter.LeftHits} hit /Right: {_counter.RightHits}";
}
[RelayCommand] private void HitLeft() { RightEnabled = !RightEnabled; }
[RelayCommand] private void HitRight() { LeftEnabled = !LeftEnabled; }
}
此代码让人困惑之处,莫过于变量名称对应不上,而这正是MVVM的核心工作,其不同字段的变化规则为
- [ObservableProperty] 用于绑定属性,将【_leftEnabled】变为【LeftEnable】,其规则是将下划线与小写字母变成大写字母。
- [RelayCommand]用于生成方法,将【HitLeft】变为【HitLeftCommand】。
最后记得修改MainWindow.xaml.cs如下
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
转自https://blog.csdn.net/m0_37816922/article/details/156588916
该文章在 2026/3/6 11:34:07 编辑过