代码改变世界

Caliburn笔记-基本Command(wpf框架)

  Clingingboy  阅读(1457)  评论(1编辑  收藏  举报

参考:http://caliburn.codeplex.com/wikipage?title=Command%20Basics&referringTitle=Documentation  

command在wpf的viewmodel中使用的非常的广泛,讨论的也非常多.

来看下caliburn对command的支持

caliburn支持三种方式command的注册

  • 容器
  • 资源
  • 绑定

Command解析字符串

parser.RegisterMessageParser("ResourceCommand", new CommandMessageParser(binder, CommandSource.Resource));
parser.RegisterMessageParser("ContainerCommand", new CommandMessageParser(binder, CommandSource.Container));
parser.RegisterMessageParser("BoundCommand", new CommandMessageParser(binder, CommandSource.Bound));

为简化xaml,在Attach中采用了特定解析的字符串,下面可以看到

1.使用容器

首先定义一个对象

注意点:

  1. 挂上Command标签
  2. 方法必须为Execute和CanExecute
[Command]
public class ShowMessageCommand
{
    //Note: A command must have an entry point.  A method named 'Execute' is searched for by default.  
    //Note: Use the CommandAttribute.ExecuteMethod to specify a different method.
    //Note: The 'Execute' method inherits all the features available to actions.
    public void Execute(string message)
    {
        MessageBox.Show(message);
    }

    //NOTE:  This is picked up automatically by the ActionFactory based on its naming convention.
    public bool CanExecute(string message)
    {
        return !string.IsNullOrEmpty(message);
    }
}


xaml

<Button Content="Attached Container Command w/ 1 Parameter" 
        cal:Message.Attach="ContainerCommand ShowMessage(message.Text)"/>


注意xaml使用方式,ContainerCommand为特定的解析字符串ShowMessage则代表ShowMessageCommand,以下规则是一样的

2.使用资源

首先然后定义对象,注意Preview标签

public class ShowTitledMessageCommand
{
    //Note: A command must have a method named 'Execute'
    //Note: The 'Execute' method inherits all the features available to actions.
    [Preview("CanExecute")]
    public void Execute(string title, string message)
    {
        MessageBox.Show(message, title);
    }

    public bool CanExecute(string title, string message)
    {
        return !string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(message);
    }
}


定义资源

<Window.Resources>
    <!--Note: Adding a command to resources.-->
    <local:ShowTitledMessageCommand x:Key="ShowTitledMessage" />
</Window.Resources>


xaml引用

<Button Content="Attached Resource Command w/ 2 Parameters"
        cal:Message.Attach="ResourceCommand ShowTitledMessage(title.Text, message.Text)" />

3.使用绑定

要绑定的前提是需要有源

首先要定义源

<Window.DataContext>
    <!--Note: Makes the presentation model available for binding through the data context.-->
    <local:MyModel />
</Window.DataContext>

使用BoundCommand绑定

<TextBox x:Name="message" />

<!--Note: Executes the command located through data binding.  The framework infers the trigger type.-->
<Button Content="Click Me!"
        cal:Message.Attach="BoundCommand TheCommand(message.Text)" />


我们通过代码来看下不同的解析过程

        protected override void SetCore(CommandMessage message, DependencyObject target, string coreOfMessage)
        {
            switch(_commandSource)
            {
                case CommandSource.Resource:
                    var frameworkElement = target as FrameworkElement;

                    if(frameworkElement != null)
                    {
                        frameworkElement.Loaded +=
                            delegate { message.Command = frameworkElement.GetResource<object>(coreOfMessage); };
                    }
                    break;
                case CommandSource.Container:
                    message.Command = ServiceLocator.Current.GetInstance(null, coreOfMessage);
                    break;
                case CommandSource.Bound:
                    var binding = new Binding(coreOfMessage);
                    BindingOperations.SetBinding(message, CommandMessage.CommandProperty, binding);
                    break;
                default:
                    throw new NotSupportedException(_commandSource + " is not a supported command source.");
            }
        }


实质上是非常简单的,主要手段还是通过给CommandMessage的Command赋值,方式不同而已.以上三种方式一比较,第一种是最简单的,这也是依赖注入带来的好处,不需要事先显示声明对象.效果都是一样的

来看下原始的用法

<Button Content="Triggers: Container Command With 1 Explicit Parameters">
    <cal:Message.Triggers>
        <cal:RoutedMessageTriggerCollection>
            <cal:EventMessageTrigger EventName="Click">
                <cal:EventMessageTrigger.Message>
                    <!--Note ResolveExtension doesn't exist in Silverlight, but you can auto resolve by string key. See SL samples.-->
                    <cal:CommandMessage Command="{cal:Resolve Key=ShowMessage}">
                        <!--Note: The declaration of parameters is different from Silverlight.-->
                        <cal:Parameter Value="{Binding ElementName=message, Path=Text}"/>
                    </cal:CommandMessage>
                </cal:EventMessageTrigger.Message>
            </cal:EventMessageTrigger>
        </cal:RoutedMessageTriggerCollection>
    </cal:Message.Triggers>
</Button>
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2007-12-29 修改服务器控件的ID和Name
点击右上角即可分享
微信分享提示