【愚公系列】2023年03月 .NET CORE工具案例-Caliburn.Micro的使用基于WPF的改造的MVVM案例
【摘要】 前言 1.Caliburn.Micro是什么Caliburn.Micro是一个微软开发的用于构建WPF,Silverlight和Windows Phone应用程序的MVVM(模型-视图-视图模型)框架。它提供了一系列的工具和类,帮助开发人员更快,更轻松地构建美观的和可维护的应用程序。 2.Caliburn.Micro的主要功能Caliburn.Micro是一个小型MVVM框架,主要提供了以...
前言
1.Caliburn.Micro是什么
Caliburn.Micro是一个微软开发的用于构建WPF,Silverlight和Windows Phone应用程序的MVVM(模型-视图-视图模型)框架。它提供了一系列的工具和类,帮助开发人员更快,更轻松地构建美观的和可维护的应用程序。
2.Caliburn.Micro的主要功能
Caliburn.Micro是一个小型MVVM框架,主要提供了以下功能:
- 简化MVVM模式的实施
- 视图绑定
- 统一方式的消息机制
- 基于事件和命令的行为触发
- 支持视图导航
- 支持Windows Phone和Silverlight平台
Caliburn.Micro 的Github网址:https://github.com/Caliburn-Micro/Caliburn.Micro
Caliburn.Micro 官网:https://caliburnmicro.com/
一、Caliburn.Micro的使用基于WPF的改造
1.项目介绍
- HelloWorld:框架的搭建、容器注入相关
- HelloWorld.Core;放置数据模型,即mvvm中的M
- HelloWorld.ViewModels:模型视图,即VM
- HelloWorld.Views:V,即视图
本项目是基于.Net 7 的
2.安装软件包
PM> Install-Package Caliburn.Micro.Start
3.改造App启动项目
1、清除 App.xaml.cs 文件
using System.Windows;
namespace HelloWorld
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
2、将 AppBoostrapper 添加到 App.xaml 的资源部分
<Application x:Class="HelloWorld.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:HelloWorld">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:Startup x:Key="startup" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
4.BootstrapperBase启动类
public class Startup : BootstrapperBase
{
SimpleContainer _container;
public Startup()
{
Initialize();
}
//配置类
protected override void Configure()
{
//这里容器采用了CM自带的SimpleContainer,并把窗口管理器和事件聚合器注册到了容器中
_container = new SimpleContainer()
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>();
//通过反射把下面三个程序集中vm结尾的视图模型文件注册到容器
foreach (var asm in SelectAssemblies())
{
foreach (var vm in asm.GetTypes())
{
if (vm.Name.EndsWith("VM"))
{
_container.RegisterPerRequest(vm, null, vm);
}
}
}
//自定义了一套CM的VM和V的匹配规则
//1.默认的规则是是:视图以View结尾、视图模型以ViewModel结尾
//2.实际规则是视图模型以VM结尾,视图只要前缀和视图模型的一致就行
var myRule = new TypeMappingConfiguration
{
ViewModelSuffix = "VM",
ViewSuffixList = new() { "" }
};
ViewLocator.ConfigureTypeMappings(myRule);
ViewModelLocator.ConfigureTypeMappings(myRule);
}
//启动类
protected override void OnStartup(object sender, StartupEventArgs e)
{
base.OnStartup(sender, e);
//设置启动视图模型
DisplayRootViewForAsync<IndexVM>();
}
/// <summary>
/// 选择程序集
/// </summary>
/// <returns></returns>
protected override IEnumerable<Assembly> SelectAssemblies()
{
return new List<Assembly>
{
Assembly.Load("HelloWorld"),
Assembly.Load("HelloWorld.Views"),
Assembly.Load("HelloWorld.ViewModels"),
};
}
/// <summary>
/// 获取实例
/// </summary>
/// <param name="service"></param>
/// <param name="key"></param>
/// <returns></returns>
protected override object GetInstance(Type service, string key)
{
return _container.GetInstance(service, key);
}
}
5.视图和视图模型详解
继承类说明:
- Screen 和 INotifyPropertyChanged (用于感知并同步所绑定属性的变化)
- IHandle<BusyMessage>:IHandle<BusyMessage>
5.1 index
5.1.1 视图模型
public class IndexVM : Screen, IHandle<BusyMessage>
{
private readonly IEventAggregator _eventAggregator;
public IndexVM(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
InitVM();
}
public string AboutTitle { get; set; }
public int BarValue { get; set; }
//通过ioc容器获取VM:
public LoginVM LoginVM { get; set; } = IoC.Get<LoginVM>();
public TableVM TableVM { get; set; } = IoC.Get<TableVM>();
public string MainName { get; set; } = "一种类似vue的使用方式,抛砖引玉";
public void AboutBtn1()
{
MessageBox.Show("Test AboutBtn1");
}
//接收事件更新进度条:
public Task HandleAsync(BusyMessage message, CancellationToken cancellationToken)
{
if (message.IsBusy)
{
BarValue = 50;
}
else
{
BarValue = 0;
}
return Task.CompletedTask;
}
protected virtual void InitVM()
{
AboutTitle = "测试AboutPage 绑定父作用域";
_eventAggregator.SubscribeOnUIThread(this);
}
}
5.1.2 视图
/// <summary>
/// Index.xaml 的交互逻辑
/// </summary>
public partial class Index : Window
{
public Index()
{
InitializeComponent();
}
}
<Window x:Class="HelloWorld.Views.Areas.Home.Index"
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:home="clr-namespace:HelloWorld.Views.Areas.Home"
xmlns:account="clr-namespace:HelloWorld.Views.Areas.Account"
xmlns:cal="http://caliburnmicro.com"
xmlns:fa="http://schemas.awesome.incremented/wpf/xaml/fontawesome.sharp"
Title="{Binding MainName}"
mc:Ignorable="d" Width="800" Height="600"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TabControl TabStripPlacement="Left">
<TabItem>
<TabItem.Header>
<StackPanel>
<fa:IconBlock Icon="Table" FontSize="24" />
<TextBlock>Table</TextBlock>
</StackPanel>
</TabItem.Header>
<home:Table cal:Bind.ModelWithoutContext="{Binding}" DataContext="{Binding TableVM}" />
</TabItem>
<TabItem>
<TabItem.Header>
<StackPanel>
<fa:IconBlock Icon="CircleInfo" FontSize="24" />
<TextBlock>About</TextBlock>
</StackPanel>
</TabItem.Header>
<home:About cal:Bind.Model="{Binding}" DataContext="{Binding}" />
</TabItem>
<TabItem>
<TabItem.Header>
<StackPanel>
<fa:IconBlock Icon="UserCircle" FontSize="24" />
<TextBlock>Login</TextBlock>
</StackPanel>
</TabItem.Header>
<account:Login cal:Bind.ModelWithoutContext="{Binding}" DataContext="{Binding LoginVM}" />
</TabItem>
</TabControl>
<ProgressBar Grid.Row="1" Value="{Binding BarValue}" Minimum="0" Maximum="100" />
</Grid>
</Window>
因为About是绑定Index所以公用事件和变量
<UserControl x:Class="HelloWorld.Views.Areas.Home.About"
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:HelloWorld.Views.Areas.Home"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Margin="30">
<TextBlock FontSize="20">
<Run Text="Title:" />
<Run Text="{Binding AboutTitle}" />
</TextBlock>
<Button x:Name="AboutBtn1" >测试按钮</Button>
</StackPanel>
</Grid>
</UserControl>
5.2 Login
注意以下代码是它通过load函数接在view
cal:Message.Attach="[Event Loaded]=[Loaded($view,$eventArgs)]"
public void Loaded(UserControl control, RoutedEventArgs @event)
{
Debug.WriteLine(control);
Debug.WriteLine(@event);
}
5.2.1 视图模型
public class LoginVM : Screen
{
private readonly IEventAggregator _eventAggregator;
public LoginVM(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public string Password { get; set; } = "123";
public string UserName { get; set; } = "王小虎";
public async Task DoLogin()
{
await _eventAggregator.PublishOnBackgroundThreadAsync(new BusyMessage(true));
await Task.Delay(1000);
MessageBox.Show("Test Login Success");
await _eventAggregator.PublishOnBackgroundThreadAsync(new BusyMessage(false));
}
public void Loaded(UserControl control, RoutedEventArgs @event)
{
Debug.WriteLine(control);
Debug.WriteLine(@event);
}
}
5.2.2 视图
<UserControl x:Class="HelloWorld.Views.Areas.Account.Login"
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:HelloWorld.Views.Areas.Account"
xmlns:cal="http://caliburnmicro.com"
cal:Message.Attach="[Event Loaded]=[Loaded($view,$eventArgs)]"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Margin="50">
<TextBlock FontSize="24">测试组件绑定自己的vm作用域</TextBlock>
<DockPanel Margin="0 10">
<Label Width="100">用户名:</Label>
<TextBox x:Name="UserName" />
</DockPanel>
<DockPanel Margin="0 10">
<Label Width="100">密码:</Label>
<TextBox x:Name="Password" />
</DockPanel>
<Button x:Name="DoLogin" Width="120">Login</Button>
</StackPanel>
</Grid>
</UserControl>
5.3 Login
5.3.1 视图模型
public class TableVM : Screen
{
private List<Foo> _data = new();
public TableVM()
{
InitData();
}
public ObservableCollection<Foo> Data { get; set; }
public bool IsShow { get; set; }
public void Loaded()
{
IsShow = true;
}
public void Unloaded()
{
IsShow = false;
}
private void InitData()
{
Task.Run(async () =>
{
while (true)
{
if (IsShow)
{
_data.Add(new Foo
{
Id = Guid.NewGuid(),
Name = "John" + new Random().Next(1, 100),
School = "上海大学"
});
Data = new ObservableCollection<Foo>(_data);
}
await Task.Delay(1000);
}
});
}
}
/// <summary>
/// 核心模型或许来自网站项目的
/// </summary>
[AddINotifyPropertyChangedInterface]
public class Foo : HelloWorld.Core.Models.Foo
{
}
5.3.2 视图
<UserControl x:Class="HelloWorld.Views.Areas.Home.Table"
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:HelloWorld.Views.Areas.Home"
xmlns:cal="http://caliburnmicro.com"
cal:Message.Attach="[Event Loaded]=[Loaded];[Event Unloaded]=[Unloaded]"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<DataGrid ItemsSource="{Binding Data}" IsReadOnly="True"/>
</Grid>
</UserControl>
源码下载:https://download.csdn.net/download/aa2528877987/87459517
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)