Ay写给2022的纯xaml [wpf4net5] - Caliburn Micro-Coroutine协程[4/16]

这里我们会用CM的 IResult接口

我们先定义个ResultBase,后面每个任务都继承ResultBase

新建一个Results文件夹

using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace cm1.Results
{
    public abstract class ResultBase : IResult
    {
        public abstract void Execute(CoroutineExecutionContext context);

        public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };

        protected virtual void OnCompleted()
        {
            OnCompleted(new ResultCompletionEventArgs());
        }

        protected virtual void OnError(Exception error)
        {
            OnCompleted(new ResultCompletionEventArgs
            {
                Error = error
            });
        }

        protected virtual void OnCancelled()
        {
            OnCompleted(new ResultCompletionEventArgs
            {
                WasCancelled = true
            });
        }

        protected virtual void OnCompleted(ResultCompletionEventArgs e)
        {
            Caliburn.Micro.Execute.OnUIThread(() => Completed(this, e));
        }
    }
}
}

这里有个很常用的类Execute,用于在非UI线程 处理业务时候,然后切换到界面线程去执行指定Action的,还有判断是不是在开发模式还是运行模式InDesignMode

image.png

CM中提供了一个实现了IResult的TaskResult方便您使用,顺便提供了TaskExtensions可以把Task转为IResult

新建一个VisualStateResult用于切换一个UI过渡VisualState

public class VisualStateResult : ResultBase
    {
        public VisualStateResult(string stateName, bool useTransitions = true)
        {
            StateName = stateName;
            UseTransitions = useTransitions;
        }

        public string StateName { get; }

        public bool UseTransitions { get; }

        public override void Execute(CoroutineExecutionContext context)
        {

            if (!(context.View is FrameworkElement))
                throw new InvalidOperationException("View must be a FrameworkElement to use VisualStateResult");

            var view = (FrameworkElement)context.View;

            var success = VisualStateManager.GoToElementState(view, StateName, UseTransitions);

            OnCompleted();
        }
    }

新建一个MessageDialogResult 用于弹窗提示

    public class MessageDialogResult : ResultBase
    {
        private readonly string content;
        private readonly string title;

        public MessageDialogResult(string content, string title)
        {
            this.content = content;
            this.title = title;
        }



        public override void Execute(CoroutineExecutionContext context)
        {
            MessageBox.Show(content, title, MessageBoxButton.OK);

            OnCompleted();
        }
    }

新建 CoroutineViewModel 使用这些IResult,CM的CoroutineExecutionContext会传递执行上一个的执行的情况

using System.Collections.Generic;
using Caliburn.Micro;
using cm1.Results;

namespace cm1.ViewModels
{
    public class CoroutineViewModel : Screen
    {
        public IEnumerable<IResult> Execute()
        {
            yield return new VisualStateResult("加载中");

            yield return TaskHelper.Delay(2000).AsResult();

            yield return new VisualStateResult("加载完成");

            yield return new MessageDialogResult("来自IResult的消息的弹窗", "IResult Coroutines");
        }
    }

}

CoroutineView.xaml

<Page x:Class="cm1.Views.CoroutineView"
      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="CoroutineView">

    <StackPanel>
        <ProgressBar x:Name="LoadingBar" Minimum="0" Maximum="100" IsIndeterminate="True" Height="20" Visibility="Hidden" />

        <Button x:Name="Execute" Content="Execute Coroutine" Margin="40,20"/>

    </StackPanel>

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="LoadingStateGroup">
            <VisualState x:Name="Loading">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LoadingBar" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="LoadingComplete"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Page>

Page有个LoadingStateGroup的状态组,有2个状态,Loading 显示进度条,LoadingComplete状态

打开Bootstrapper.cs 修改

  .PerRequest<CoroutineViewModel>()

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

        }

打开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)),
            };

运行项目

效果

image.png

image.png

我们设置断点,观看CoroutineExecutionContext

image.png

传递过来了 单击的是按钮,哪个viewmodel和对应的view

这里IResult 的 添加顺序,决定了执行顺序,然后会通过CoroutineExecutionContext 传递

本文由 安徽 合肥 杨洋 1991年的 英文名AY   

本文由 安徽 合肥 杨洋 1991年的 英文名AY   

本文代码下载:Download

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值