时间:2021年09月26日 | 作者 : aaronyang | 分类 : WPF | 浏览: 858次 | 评论 0 人
相关文章
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro[1/16],MyGet-WPF-aaronyang技术分享 (ayjs.net) Download
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro-绑定[2/16]-WPF-aaronyang技术分享 (ayjs.net) Download
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro-调用vm的方法[3/16]-WPF-aaronyang技术分享 (ayjs.net) Download
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro-Coroutine协程[4/16]-WPF-aaronyang技术分享 (ayjs.net) Download
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro-Execute 异步里面更新界面UI[5/16]-WPF-aaronyang技术分享 (ayjs.net)
第5天CM.zip
Ay写给2022的纯xaml [wpf4net5] - Caliburn-Micro-EventAggregation[6/16]-WPF-aaronyang技术分享 (ayjs.net)
第6天CM.zip
Ay写给2022的纯xaml [wpf4net5] - Caliburn Micro-Conductor[7/16]-WPF-aaronyang技术分享 (ayjs.net)
第7天CM.zip
Ay写给2022的纯xaml [wpf4net5] - Caliburn Micro-Bubbling[8/16]-WPF-aaronyang技术分享 (ayjs.net)
第8天CM.zip
通过发布订阅的方式 在VM之间 传递界面与界面的操作
在多个需要传递操作的vm中也需要加
添加 EventAggregationViewModel
using Caliburn.Micro; namespace cm1.ViewModels { public class EventAggregationViewModel : Screen { public EventAggregationViewModel(IEventAggregator eventAggregator) { } } }
打开Bootstrapper.cs 修改
protected override void Configure() { container = new SimpleContainer(); container.Instance(container); container .Singleton<IWindowManager, WindowManager>() .Singleton<IEventAggregator, EventAggregator>(); container .PerRequest<ShellViewModel>() .PerRequest<MenuViewModel>() .PerRequest<BindingsViewModel>() .PerRequest<ActionsViewModel>() .PerRequest<CoroutineViewModel>() .PerRequest<ExecuteViewModel>() .PerRequest<EventAggregationViewModel>(); }
打开MenuViewModel.cs添加菜单
Features = new BindableCollection<FeatureViewModel> { new FeatureViewModel("Binding Conventions", "Binding view model properties to your view.", typeof(BindingsViewModel)), new FeatureViewModel("Action Conventions", "Wiring view events to view model methods.", typeof(ActionsViewModel)), new FeatureViewModel("Coroutines", "Using IEnumerable<IResult>", typeof(CoroutineViewModel)), new FeatureViewModel("Execute", "Using Execute to execute code on the UI thread.", typeof(ExecuteViewModel)), new FeatureViewModel("Event Aggregator", "在非耦合视图模型之间发送事件.", typeof(EventAggregationViewModel)), };
在CM中 在xaml里面通过VM呈现个 UserControl可以使用下面方式,当然你也可以直接导入空间,直接写控件。
<ContentControl cal:View.Model="{Binding VM类型的实例}" />
先建立一个消息的结构,这里只考虑文本,建立Messages文件夹
namespace cm1.Messages { public class SimpleMessage { public SimpleMessage(string text) { Text = text; } public string Text { get; } } }
在EventAggregationView里面有2个usercontrol, 2个uc对应2个vm
现在要解决2个vm的通讯,因为2个vm都没有对方的实例,所以有点难度了,通过CM的EventAggregation可以解决
在ViewModels建立Events文件夹,名字你随意取的
建立发送消息的EventSourceViewModel
using System; using System.Threading; using Caliburn.Micro; using cm1.Messages; namespace cm1.ViewModels.Events { public class EventSourceViewModel : Screen { private readonly IEventAggregator eventAggregator; public EventSourceViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; } private string text; public string Text { get { return text; } set { Set(ref text, value); } } public async void Publish() { } } }
界面1个文本框,放消息内容的,一个按钮发布这个消息
<UserControl x:Class="cm1.Views.Events.EventSourceView" 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" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <StackPanel Margin="20"> <TextBlock Text="发送的内容"/> <TextBox x:Name="Text" /> <Button x:Name="Publish" Content="发布" Margin="0,10"/> </StackPanel> </Grid> </UserControl>
接下来 建立EventAggregationView 通过ContentControl显示这个usercontrol
<Page x:Class="cm1.Views.EventAggregationView" 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" mc:Ignorable="d" xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform" d:DesignHeight="300" d:DesignWidth="300" Title="EventAggregationView"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ContentControl cal:View.Model="{Binding Source}" Grid.Column="0"/> </Grid> </Page>
修改EventAggregationViewModel
using Caliburn.Micro; using cm1.ViewModels.Events; namespace cm1.ViewModels { public class EventAggregationViewModel : Screen { public EventAggregationViewModel(IEventAggregator eventAggregator) { Source = new EventSourceViewModel(eventAggregator); } public EventSourceViewModel Source { get; } } }
接下来添加右侧的vm,我们叫 EventDestinationViewModel这个名字
using System; using System.Threading; using System.Threading.Tasks; using Caliburn.Micro; using cm1.Messages; namespace cm1.ViewModels.Events { public class EventDestinationViewModel : Screen, IHandle<SimpleMessage> { private readonly IEventAggregator eventAggregator; public EventDestinationViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; Messages = new BindableCollection<SimpleMessage>(); } public void Subscribe() { eventAggregator.SubscribeOnPublishedThread(this); } public void Unsubscribe() { eventAggregator.Unsubscribe(this); } public Task HandleAsync(SimpleMessage message, CancellationToken cancellationToken) { Messages.Add(message); return Task.FromResult(true); } public BindableCollection<SimpleMessage> Messages { get; } } }
添加1个Messages,用来显示历史消息
作为1个消息处理方,也就是 订阅方,需要实现IHandle<T>接口
public Task HandleAsync(SimpleMessage message, CancellationToken cancellationToken) { Messages.Add(message); return Task.FromResult(true); }
我们收到消息,直接放入集合了
界面上2个按钮,一个叫Subscribe 一个叫Unsubscribe ,通过调用IEventAggregator 的2个方法
下方放个文本列表
EventDestinationView的界面如下
<UserControl x:Class="cm1.Views.Events.EventDestinationView" 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" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <StackPanel Margin="20"> <Button x:Name="Subscribe" Content="开始订阅" /> <Button x:Name="Unsubscribe" Content="取消订阅" Margin="0,10" /> <ItemsControl x:Name="Messages"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Text}"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </Grid> </UserControl>
接下来把这个vm放入EventAggregationView显示
EventAggregationView代码如下:
<Page x:Class="cm1.Views.EventAggregationView" 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" mc:Ignorable="d" xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform" d:DesignHeight="300" d:DesignWidth="300" Title="EventAggregationView"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ContentControl cal:View.Model="{Binding Source}" Grid.Column="0"/> <ContentControl cal:View.Model="{Binding Destination}" Grid.Column="1"/> </Grid> </Page>
using Caliburn.Micro; using cm1.ViewModels.Events; namespace cm1.ViewModels { public class EventAggregationViewModel : Screen { public EventAggregationViewModel(IEventAggregator eventAggregator) { Source = new EventSourceViewModel(eventAggregator); Destination = new EventDestinationViewModel(eventAggregator); } public EventSourceViewModel Source { get; } public EventDestinationViewModel Destination { get; } } }
using System; using System.Threading; using Caliburn.Micro; using Features.CrossPlatform.Messages; namespace Features.CrossPlatform.ViewModels.Events { public class EventSourceViewModel : Screen { private readonly IEventAggregator eventAggregator; private string text; public EventSourceViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; } public string Text { get { return text; } set { Set(ref text, value); } } public async void Publish() { await eventAggregator.PublishOnUIThreadAsync(new SimpleMessage(Text), CancellationToken.None); } } }
运行项目:
测试1:
输入内容,单击发送,右侧没文字
测试2
点击开始订阅 , 输入内容,点击发布,右侧收到了消息并且处理
测试3
继续点击开始订阅 , 输入内容,点击发布,右侧收到了消息并且处理, CM没有重复订阅,是单个类型处理的
测试4
点击取消订阅 , 输入内容,点击发布,右侧无法收到消息
测试5
多添加一个同类型EventDestinationViewModel的Destination2实例
using Caliburn.Micro; using cm1.ViewModels.Events; namespace cm1.ViewModels { public class EventAggregationViewModel : Screen { public EventAggregationViewModel(IEventAggregator eventAggregator) { Source = new EventSourceViewModel(eventAggregator); Destination = new EventDestinationViewModel(eventAggregator); Destination2 = new EventDestinationViewModel(eventAggregator); } public EventSourceViewModel Source { get; } public EventDestinationViewModel Destination { get; } public EventDestinationViewModel Destination2 { get; } } }
界面修改
<Page x:Class="cm1.Views.EventAggregationView" 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" mc:Ignorable="d" xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform" d:DesignHeight="300" d:DesignWidth="300" Title="EventAggregationView"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ContentControl cal:View.Model="{Binding Source}" Grid.Column="0"/> <ContentControl cal:View.Model="{Binding Destination}" Grid.Column="1"/> <ContentControl cal:View.Model="{Binding Destination2}" Grid.Column="2"/> </Grid> </Page>
运行后,得出结论,多个同类型的实例,互不干扰,每个实例比如手动把自己注册到事件聚合器,他不像MVVMLight根据vm类型来注册的
测试6
复制一个处理方VM,叫EventDestinationViewModel2 内容和EventDestinationViewModel一样,修改
using Caliburn.Micro; using cm1.ViewModels.Events; namespace cm1.ViewModels { public class EventAggregationViewModel : Screen { public EventAggregationViewModel(IEventAggregator eventAggregator) { Source = new EventSourceViewModel(eventAggregator); Destination = new EventDestinationViewModel(eventAggregator); Destination2 = new EventDestinationViewModel2(eventAggregator); } public EventSourceViewModel Source { get; } public EventDestinationViewModel Destination { get; } public EventDestinationViewModel2 Destination2 { get; } } }
public class EventDestinationViewModel2 : Screen, IHandle<SimpleMessage> { private readonly IEventAggregator eventAggregator; public EventDestinationViewModel2(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; Messages = new BindableCollection<SimpleMessage>(); } public void Subscribe() { eventAggregator.SubscribeOnPublishedThread(this); } public void Unsubscribe() { eventAggregator.Unsubscribe(this); } public Task HandleAsync(SimpleMessage message, CancellationToken cancellationToken) { Messages.Add(message); return Task.FromResult(true); } public BindableCollection<SimpleMessage> Messages { get; } }
运行后,得出结论,CM是根据全名称匹配VM和View的
测试7
一个处理方同时处理 多种类型消息
添加
public class SimpleMessage2 { public SimpleMessage2(string text,int aa) { Text = text; AA = aa; } public string Text { get; } public int AA { get; } }
处理方修改
public class EventDestinationViewModel : Screen, IHandle<SimpleMessage>, IHandle<SimpleMessage2> { private readonly IEventAggregator eventAggregator; public EventDestinationViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; Messages = new BindableCollection<SimpleMessage>(); } public void Subscribe() { eventAggregator.SubscribeOnPublishedThread(this); } public void Unsubscribe() { eventAggregator.Unsubscribe(this); } public Task HandleAsync(SimpleMessage message, CancellationToken cancellationToken) { Messages.Add(message); return Task.FromResult(true); } public Task HandleAsync(SimpleMessage2 message, CancellationToken cancellationToken) { Messages.Add(new SimpleMessage("消息2:"+message.Text)); return Task.FromResult(true); } public BindableCollection<SimpleMessage> Messages { get; } }
发布方,多加一种类型的消息
using System; using System.Threading; using Caliburn.Micro; using cm1.Messages; namespace cm1.ViewModels.Events { public class EventSourceViewModel : Screen { private readonly IEventAggregator eventAggregator; public EventSourceViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; } private string text; public string Text { get { return text; } set { Set(ref text, value); } } public async void Publish() { await eventAggregator.PublishOnUIThreadAsync(new SimpleMessage(Text), CancellationToken.None); await eventAggregator.PublishOnUIThreadAsync(new SimpleMessage2(Text,10), CancellationToken.None); } } }
运行后,2种消息都可以处理了,1个页面可以会被多个VM 发送消息和处理,比如主窗体的VM
结论1:
UserControl的VM不需要放入 Bootstrapper的configure显示注册
结论2:
CM的事件发布和订阅。订阅方要先 订阅,才能收到自己要的类型消息,并且处理、
应该是根据自己的 实例来的,不是根据实例的类型
本文由 安徽 合肥 杨洋 1991年的 英文名AY ===来自网站 www.ayjs.net 编写
本文由 安徽 合肥 杨洋 1991年的 英文名AY ===来自网站 www.ayjs.net 编写
本文代码下载:
net framework 类库 | net5 中的替代类库 |
Microsoft.Expression.Interactions System.Windows.Interactivity | Microsoft.Xaml.Behaviors.Wpf |
其他Ay准备升级到net5的纯xaml库
【ay wpf markup】AY XAML应该这样玩【1/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩【2/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-写个计算器【3/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-for循环【4/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-ChangedHandler【5/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-ResourceCollection和ScriptHandler【6/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-ResourceObject【7/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-ScriptHandler组合,也是最常用的【8/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-语法集合【9/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-Tower of Hanoi【10/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-写个简单的移动【11/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-写个复杂的绘图【12/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-写个复杂的颜色环【13/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-获得焦点全选【14/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-把Additional.Operations当资源【15/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-给ListView创建数据【16/18】-WPF-aaronyang技术分享 (ayjs.net)
【ay wpf markup】AY XAML应该这样玩-和后台ViewModel交互,操作方法【17/18】-WPF-aaronyang技术分享 (ayjs.net)
Window
<Window x:Class="Features.CrossPlatform.Views.ShellView" 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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform" mc:Ignorable="d" Title="ShellView" Height="450" Width="800"> <Grid> </Grid> </Window>
Page
<Page x:Class="Features.CrossPlatform.Views.MenuView" 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" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Title=""> <Grid> </Grid> </Page>
UserControl
<UserControl x:Class="cm1.Views.FeatureView" 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:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> </Grid> </UserControl>
抖音:wpfui 工作wpf,目前主maui
招聘合肥一枚WPF工程师,跟我一个开发组,10-15K,欢迎打扰
目前在合肥市企迈科技就职
AYUI8全源码 Github地址:前往获取
杨洋(AaronYang简称AY,安徽六安人)和AY交流
高中学历,2010年开始web开发,2015年1月17日开始学习WPF
声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费
不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo
查看捐赠AYUI7.X MVC教程 更新如下:
第一课 第二课 程序加密教程
额 本文暂时没人评论 来添加一个吧
发表评论