当前位置:网站首页 / WPF / 正文

Ay写给2022的纯xaml [wpf4net5] - Caliburn Micro-EventAggregation[6/16]

时间:2021年09月26日 | 作者 : aaronyang | 分类 : WPF | 浏览: 328次 | 评论 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; }

    }

}

image.png


接下来添加右侧的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; }
    }

}

作为1个消息发送方,通过  await eventAggregator.PublishOnUIThreadAsync(对象实例, CancellationToken.None);

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);
        }
    }
}


运行项目:

image.png

image.png


测试1:

输入内容,单击发送,右侧没文字


测试2

点击开始订阅 , 输入内容,点击发布,右侧收到了消息并且处理


测试3

继续点击开始订阅 , 输入内容,点击发布,右侧收到了消息并且处理, CM没有重复订阅,是单个类型处理的



测试4

点击取消订阅 , 输入内容,点击发布,右侧无法收到消息

image.png


测试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类型来注册的

image.png


测试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

image.png


结论1:

UserControl的VM不需要放入 Bootstrapper的configure显示注册


结论2:

CM的事件发布和订阅。订阅方要先 订阅,才能收到自己要的类型消息,并且处理、

应该是根据自己的 实例来的,不是根据实例的类型





本文由 安徽 合肥 杨洋 1991年的 英文名AY   ===来自网站 www.ayjs.net 编写

本文由 安徽 合肥 杨洋 1991年的 英文名AY   ===来自网站 www.ayjs.net 编写


本文代码下载:

第6天CM.zip


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>








推荐您阅读更多有关于“wpfcm,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

合肥科大智能常年招聘C# .NET CORE,vue前端,JAVA开发,有想换工作的私聊我AY唯一QQ:875556003和AY交流

抖音号:wpfui 工作是wpf,不接活,目前主要折腾maui

AYUI8社区版Github地址:前往获取

杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2010年开始web开发,2015年1月17日开始,兴趣学习研究WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表