首页 > 其他分享 >Prism 行为处理

Prism 行为处理

时间:2024-09-29 16:24:40浏览次数:9  
标签:DelegateCommand get 处理 value 命令 Prism 行为 public 属性

Prism框架提供了DelegateCommand类型,专门用于进行WPF中的行为处理。

基本使用
一、命令的使用
DelegateCommand(Action executeMethod):DelegateCommand的构造函数,创建DelegateCommand对象。

executeMethod:无参的命令执行函数。
定义命令

public class MainViewModel
{
    public ICommand BtnCommand => new DelegateCommand(Execute);

    private void Execute()
    {
        //做命令执行业务
    }
}
<Window ......>
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <Button Content="BtnCommand" Command="{Binding BtnCommand}"/>
        </StackPanel>
    </Grid>
</Window>

带参数的命令

Prism框架中,命令的使用跟MVVMToolkit框架是类似的,命令的执行函数可以有参,也可以无参,具体用法如下:

public ICommand BtnCommand => new DelegateCommand<string>(Execute);

private async void Execute(string str)
{
    await Task.Delay(2000);
    Value = 100;
}

二、命令的状态检查
Prism提供了三种命令状态检查方式

1、方式1:调用RaiseCanExecuteChanged方法
可以向DelegateCommand的构造函数中传入状态检查的委托函数。然后在合适的节点去调用DelegateCommand对象的RaiseCanExecuteChanged方法来执行状态检查函数。

DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod):DelegateCommand的构造函数,创建DelegateCommand对象。

executeMethod:无参的命令执行函数。
canExecuteMethod:命令的状态检查函数。
RaiseCanExecuteChanged():调用DelegateCommand对象的命令状态检查函数(构造时传入的函数)。

定义命令

需要注意以下两点:

RaiseCanExecuteChanged():此方法是DelegateCommand对象的方法,ICommand接口中没有,为了后续方便,创建时直接使用DelegateCommand而不是ICommand类型。
DelegateCommand对象的初始化(new)必须放在所在类型的构造函数中进行,否则调用RaiseCanExecuteChanged函数不起作用。

public class MainViewModel
{
    private int _value = 10;

    public int Value
    {
        get { return _value; }
        set { 
            _value = value;
            //调用命令状态检查函数
            BtnCheckCommand.RaiseCanExecuteChanged();
        }
    }
    //声明属性,但不做初始化,留在构造函数中做
    public DelegateCommand BtnCheckCommand { get; }
    private bool CheckCanExecute()
    {
        return Value == 100;
    }
        private void Execute()
    {
        //做命令执行业务
    }
    public MainViewModel()
    {
        //继续命令初始化,只能放在这里做,放在属性中进行初始化的话,调用状态检查函数无效果。
        BtnCheckCommand = new DelegateCommand(Execute, CheckCanExecute);
    }
}

2、方式2:使用ObservesProperty监听属性变化
DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod):DelegateCommand的构造函数,创建DelegateCommand对象。

executeMethod:无参的命令执行函数。
canExecuteMethod:命令的状态检查函数。
DelegateCommand ObservesProperty<T>(Expression<Func<T>> propertyExpression):DelegateCommand对象的方法,用于监听指定属性的变化,一旦属性发生变化,就调用构造时传入的状态检查函数。

propertyExpression:一个返回指定监控属性的无参Lambda表达式。
由于调用后就返回监听该属性的DelegateCommand对象,因此可以通过链式调用监听多个属性的变化。

public class MainWindowViewModel : BindableBase
{
    private int _value1;

    public int Value1
    {
        get { return _value1; }
        set { SetProperty(ref _value1, value); }
    }

    private int _value2;

    public int Value2
    {
        get { return _value2; }
        set { SetProperty(ref _value2, value); }
    }


    private void Execute()
    {
        //做命令执行业务
    }

    public DelegateCommand BtnCheckCommand { get; }
    private bool CheckCanExecute()
    {
        return Value1 + Value2 == 100;
    }

    public MainWindowViewModel()
    {
        BtnCheckCommand = new DelegateCommand(Execute, CheckCanExecute)
            .ObservesProperty(() => Value1)
            .ObservesProperty(() => Value2);//通过链式结构可以同时监听多个属性,进行组合判断
    }
}

这种方式比第1种方式要更加方便,不用考虑在哪个地方去主动调用命令状态检查函数。

3、方式3:使用ObservesProperty
DelegateCommand ObservesCanExecute(Expression<Func<bool>> canExecuteExpression):DelegateCommand的实例方法,根据传入的Lambda表达式,来检查命令的可执行状态。

canExecuteExpression:一个返回bool类型属性的表达式。
注意

传递给ObservesCanExecute的Lambda表达式中,需要返回bool类型的属性而不是直接的bool值,否则无效。

传递给ObservesCanExecute的Lambda表达式中返回的属性,有两点需要注意:

必须做属性变化通知处理。
在第二次属性变化通知起,才能正确完成命令可执行状态检查,也就是第一次变化通知不会正常完成命令状态检查,需要提前做一下第一次的属性变化。
此属性发生变化时才会触发命令可执行状态检查,因此要在合适的时候去改变属性来触发检查。
命令定义

public class MainViewModel: BindableBase
{
    private int _value = 10;

    public int Value
    {
        get { return _value; }
        set
        {
            _value = value;
            //在合适的时机去改变Status属性,触发变化通知,从而调用状态检查
            Status = !Status;
        }
    }

    public bool status = false;
    public bool Status
    {
        get { return Value == 100; }
        set 
        {
            //一定要做属性变化通知,以此来触发状态检查
            SetProperty(ref status, value); 
        }
    }

    private void Execute()
    {
        //做命令执行业务
    }

    public DelegateCommand BtnCheckCommand { get; }

    public MainViewModel()
    {
        //与前两中方式相比,可以不需要传入命令状态检查函数
        BtnCheckCommand = new DelegateCommand(Execute).ObservesCanExecute(()=> Status);
        Status = !Status;//要先触发一次Status的属性变化通知,在第二次属性变化通知时才能顺利的检查命令的状态
    }
}

三、异步处理

Prism的异步处理没什么新鲜的,就是正常的使用异步函数,具体如下

public ICommand BtnCommand
{
    get => new DelegateCommand(Execute);
}

private async void Execute()
{
    await Task.Delay(2000);
    Value = 100;
}

一、事件触发命令

定义命令

public class MainViewModel: BindableBase
{
    private int value = 10;

    public int Value
    {
        get { return value; }
        set 
        {
            SetProperty(ref this.value, value);    
        }
    }

    public ICommand BtnCommand { get => new DelegateCommand<object>(Execute); }

    private void Execute(object obj)
    {
        Value = 100;
    }

}

xaml中绑定命令

注意,这里因为使用了Prism框架的命令,因此在绑定命令时使用了prism:InvokeCommandAction。如果没有使用Prism框架,可以使用i:InvokeCommandAction,也就是Behaviors包自带的。

<Window ......
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:prism="http://prismlibrary.com/"
        ......>
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding Value}"/>
            <ComboBox SelectedIndex="0">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <prism:InvokeCommandAction Command="{Binding BtnCommand}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <ComboBoxItem Content="item1"/>
                <ComboBoxItem Content="item2"/>
                <ComboBoxItem Content="item3"/>
                <ComboBoxItem Content="item4"/>
            </ComboBox>
        </StackPanel>
    </Grid>
</Window>

注意

默认情况下,上述做法会直接将EventArgs对象作为参数传递给命令执行函数,如果需要进行参数的指定,可以通过prism:InvokeCommandAction元素的TriggerParameterPath属性来将EventArgs中的某个属性成员作为参数传入,或者使用CommandParameter属性,将其他对象作为参数传递给命令执行函数。如果同时使用TriggerParameterPath和CommandParameter属性,则优先传递CommandParameter属性设置的参数。

例如:<prism:InvokeCommandAction Command="{Binding BtnCommand}" TriggerParameterPath="Handled"/>就是将EventArgs对象中的Handled属性作为参数传递给命令执行函数。

二、事件触发方法
在Behaviores包的帮助下,也可以直接让事件来触发指定的方法。

定义执行方法

public class MainWindowViewModel
{
    public void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            //输入键
        }
    }
}

注意,事件处理方法会接收到几个默认的参数,如果不知道是什么参数对象可以通过在控件中自动生成事件方法来参考一下。在本例中可以通过<TextBox …… KeyDown="TextBox_KeyDown">,自动生成TextBox_KeyDown方法来查看接收什么参数。

XAML中使用

注意,这里使用的是b:CallMethodAction,是Behaviors包中提供的对象。

TargetObject:指定事件处理方法所在的对象。

MethodName:事件处理方法的名称。

<Window ......
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors">
    <Grid>
        <TextBox Height="30" Width="100">
            <b:Interaction.Triggers>
                <b:EventTrigger EventName="KeyDown">
                    <b:CallMethodAction TargetObject="{Binding}" MethodName="TextBox_KeyDown"/>
                </b:EventTrigger>
            </b:Interaction.Triggers>
        </TextBox>
    </Grid>
</Window>

复合命令
复合命令是指一个命令可以同时完成多个命令,Prism提供了CompositeCommand类型专门用于实现复合命令。

注册命令

RegisterCommand(ICommand command):CompositeCommand的实例方法,用于注册命令,也就是将指定命令添加到当前复合命令对象中。

UnregisterCommand(ICommand command):CompositeCommand的实例方法,用于取消注册指定命令,即从当前复合命令对象中移除指定命令。

同一个模块(例如要复合的命令全部都在MainWindowViewModel中)的复合命令是很容易实现的,即使不使用CompositeCommand也可以实现。然而在实际开发中,要用到复合命令的情景往往是需要将多个不同模块中的命令集中起来一次性全部调用。这个过程不仅需要使用到CompositeCommand类,还需要借助IOC容器的依赖注入来实现。

<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:prism="http://prismlibrary.com/"
        Title="MainWindow"
        Width="800"
        Height="450"
        prism:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="150" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <UniformGrid Rows="2">
            <Button Command="{Binding UnionCommand.Commands}" Content="UnionCommand" />
            <UniformGrid Columns="2">
                <Button Command="{Binding ShowViewACommand}" Content="ViewA" />
                <Button Command="{Binding ShowViewBCommand}" Content="ViewB" />
            </UniformGrid>
        </UniformGrid>
        <UniformGrid Grid.Row="1" Rows="1">
            <ContentControl prism:RegionManager.RegionName="ViewA" />
            <ContentControl prism:RegionManager.RegionName="ViewB" />
        </UniformGrid>
    </Grid>
</Window>
public class MainWindowViewModel : BindableBase
    {
        [Dependency]
        public IRegionManager regionManager { get; set; }

        public MainWindowViewModel(IRegionManager regionManager, IUnionCommand UnionCommand)
        {
            this.regionManager = regionManager;
            this.UnionCommand = UnionCommand;
        }
        [Dependency]
        public IUnionCommand UnionCommand { get; set; }
        public ICommand ShowViewACommand
        {
            get => new DelegateCommand(() =>
            {
                regionManager.RequestNavigate("ViewA", "ViewA");
            });
        }
        public ICommand ShowViewBCommand
        {
            get => new DelegateCommand(() =>
            {
                regionManager.RequestNavigate("ViewB", "ViewB");
            });
        }
    }
<UserControl x:Class="WpfApp1.Views.ViewA"
             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:local="clr-namespace:WpfApp1.Views"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             d:DesignHeight="450"
             d:DesignWidth="800"
             mc:Ignorable="d">
    <Grid>
        <StackPanel VerticalAlignment="Center">
            <TextBox Text="{Binding ValueA}" />
            <Button Command="{Binding ValueACommand}" Content="ShouViewA" />
        </StackPanel>
    </Grid>
</UserControl>
<UserControl x:Class="WpfApp1.Views.ViewB"
             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:local="clr-namespace:WpfApp1.Views"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             d:DesignHeight="450"
             d:DesignWidth="800"
             mc:Ignorable="d">
    <Grid>
        <StackPanel VerticalAlignment="Center">
            <TextBox Text="{Binding ValueB}" />
            <Button Command="{Binding ValueBCommand}" Content="ShouViewB" />
        </StackPanel>
    </Grid>
</UserControl>
 public class ViewAViewModel : BindableBase
    {
        private int _valueA = 0;
        public int ValueA
        {
            get { return _valueA; }
            set { SetProperty(ref _valueA, value); }
        }
        public ICommand ValueACommand { get; set; }
        public ViewAViewModel(IUnionCommand unionCommand)
        {
            ValueACommand = new DelegateCommand(() =>
            {
                ValueA = 100;
            });
            //注册命令
            unionCommand.Commands.RegisterCommand(ValueACommand);
        }
    }
 public class ViewBViewModel : BindableBase
    {
        private int _valueB = 0;

        public int ValueB
        {
            get { return _valueB; }
            set { SetProperty(ref _valueB, value); }
        }

        public ICommand ValueBCommand { get; set; }

        public ViewBViewModel(IUnionCommand unionCommand)
        {
            ValueBCommand = new DelegateCommand(() =>
            {
                ValueB = 200;
            });
            //注册命令
            unionCommand.Commands.RegisterCommand(ValueBCommand);
        }
    }
 public class Startup : PrismBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            return Container.Resolve<MainWindow>();
            //return Container.Resolve<NavigationLogWindow>();
            //return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<ViewA>();
            containerRegistry.RegisterForNavigation<ViewB>();
            containerRegistry.RegisterSingleton<IUnionCommand, UnionCommand>();

            //containerRegistry.RegisterForNavigation<ViewD>();
            //containerRegistry.RegisterForNavigation<ViewE>();
        }
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
            ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), typeof(MainWindowViewModel));

            ViewModelLocationProvider.Register(typeof(NavigationWindow).ToString(), typeof(NavigationWindowVewModel));
            ViewModelLocationProvider.Register(typeof(NavigationLogWindow).ToString(), typeof(NavigationLogViewModel));
        }
       
    }
来源:https://blog.csdn.net/jjailsa/article/details/135732650

 

标签:DelegateCommand,get,处理,value,命令,Prism,行为,public,属性
From: https://www.cnblogs.com/ywtssydm/p/18440275

相关文章

  • WSL安装问题处理
    问题描述在执行 wsl--install 安装Windows子系统Linux WSL (WindowsSubsystemforLinux)时报错:无法从“https://raw.githubusercontent.com/microsoft/WSL/master/distributions/DistributionInfo.json”中提取列表分发。无法解析服务器的名称或地址Errorcode:Wsl/WI......
  • 线程的数量应当与处理器的数量的关系
    线程的数量应当与处理器的数量相匹配,否则可能会导致性能的下降而不是提升,尤其是在只有一个处理器的情况下。线程是程序执行的最小单位,它可以在不同的处理器核心上并发执行,利用多核处理器的能力来提升计算效率。处理器(CPU)核心是物理上能够执行指令的单元。一个处理器可以有一个......
  • 空指针处理方案
    空指针的bug处理出现A.xxxx的时候要考虑A如果为null的空指针异常//误报,此时first报空指针风险,但是不可能for(inti=0;i<size;i++){TreeNodefirst=queue.pollFirst();if(first.left!=null){queue.offerLast(first.left);} //处理前:re......
  • Apache伪静态出现页面无法正常访问处理
    默认规则:apache RewriteRule^(.*)$index.php/$1[QSA,PT,L]这条规则适用于Apache采用模块化运行方式的情况。当请求URL不是目录或文件时,将所有请求重写为index.php/$1。备用规则:apache RewriteRule^(.*)$index.php[E=PATH_INFO:$1,QSA,PT,L]这条......
  • 图形视频处理软件Adobe After Effects(AE2024)软件下载安装
    目录简介软件特点下载推荐硬件简介AdobeAfterEffects,简称AE,是Adobe公司推出的一款专业的图形视频处理软件。它广泛应用于电影、广告、电视等影视制作领域,特别是在视频特效和后期制作方面。AE以其强大的功能和灵活的操作,成为设计和视频特技领域的首选工具,适合电视台、......
  • 大json字符串处理
    背景:当从API获取数据或与其他系统交换信息时。有时json字符串可能会非常庞大,以至于读取到内存中会导致内存溢出或者性能问题流式处理:如果JSON字符串过大,不适合一次性加载到内存中,可以考虑使用流式处理。例如,使用Jackson库的JsonParser,可以逐行解析JSON,从而避免一次性加载整个字......
  • Prism导航
    注册导航页面注册区域使用p:RegionManager.RegionName注册页面区域<Windowx:Class="WpfApp1.NavigationWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&......
  • 推出TMS320VC5416GWS120、TMS320VC5416PGE160、TMS320VC5416ZWS160定点数字信号处理器
    系列概述:TMS320VC5416定点数字信号处理器(DSP)基于先进的改进型哈佛架构打造,具有一条程序存储器总线和三条数据存储器总线。该处理器采用具有高并行能力的算术逻辑单元(ALU)、特定于应用的硬件逻辑、片上存储器和附加片上外设。高度专业化的指令集是TMS320VC5416操作灵活性和速度的基......
  • matlab-批处理图像质量变化并形成折线图 (PSNR)
    %修改路径就能用,图片分辨率要一致%clc;clearall;closeall;tic;%清理内存file_path='E:\test\resources\image\';%批量图像所在的文件夹下file_save_path='E:\test\resources\SaveImage\';%要存储的地址img_path_list=dir(strcat(file_path,'*.jpg'));%获取批量bmp格式......
  • 火语言RPA流程组件介绍--处理网页对话框
    ......