[]
        
(Showing Draft Content)

自定义命令属性编辑控件

大部分情况下,通过标注不同的Attribute给属性,可以指定使用不同的内置属性编辑器。

但是如果希望命令通过更复杂的方式编辑就需要通过自定义一个WPF的用户组件来实现了。

1. 在MyPluginCommand中定义一个属性。

    [Designer("MyPlugin.Designer.MyPluginServerCommandDesigner, MyPlugin")]
    public class MyPluginServerCommand : Command, ICommandExecutableInServerSideAsync
    {
        [DisplayName("说明:")]
        public string MyProperty { get; set; }

        public async Task<ExecuteResult> ExecuteAsync(IServerCommandExecuteContext dataContext)
        {
            return new ExecuteResult();
        }
        public override CommandScope GetCommandScope()
        {
            return CommandScope.ExecutableInServer;
        }
    }

2. 添加一个自定义窗体。

  1. 在插件工程中Designer文件夹点击右键,选择“添加->用户控件(WPF)”。



  2. 在弹出对话框中指定名称为 MyCommandPropertyEditor.xaml。


  3. 创建成功过后分别按以下代码修改 MyCommandPropertyEditor.xaml 和 MyCommandPropertyEditor.xaml.cs 文件。

    • MyCommandPropertyEditor.xaml 文件代码说明:在控件中添加了一个多行文本框(可以根据需求加入其它控件)。

<UserControl x:Class="MyPlugin.Designer.MyCommandPropertyEditor"
             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:local="clr-namespace:MyPlugin.Designer"
             mc:Ignorable="d" 
             MinHeight="100" d:DesignWidth="800">
    <Grid x:Name="root">
        <TextBox VerticalContentAlignment="Stretch"  Margin="9,0,0,0" AcceptsReturn="True" Text="{Binding Text}"></TextBox>
    </Grid>
</UserControl>
  • MyCommandPropertyEditor.xaml.cs 文件代码说明:MyCommandPropertyEditor_DataContextChanged 通过 DataContext 属性可以和属性值互操作。

using GrapeCity.Forguncy.Plugin;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace MyPlugin.Designer
{
    public partial class MyCommandPropertyEditor : UserControl
    {
        public MyCommandPropertyEditor()
        {
            InitializeComponent();
            this.root.DataContext = new MyCommandPropertyEditorViewModel();
            this.DataContextChanged += MyCommandPropertyEditor_DataContextChanged;
        }

        private void MyCommandPropertyEditor_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (this.DataContext is IEditorSettingsDataContext editorSettingsDataContext)
            {
                this.ViewModel.Text = editorSettingsDataContext.Value?.ToString();
                this.ViewModel.PropertyChanged += (o, e2) =>
                {
                    editorSettingsDataContext.Value = this.ViewModel.Text;
                };
            }
        }

        public MyCommandPropertyEditorViewModel ViewModel
        {
            get
            {
                return this.root.DataContext as MyCommandPropertyEditorViewModel;
            }
        }

        public class MyCommandPropertyEditorViewModel : INotifyPropertyChanged
        {

            private string _text;
            public string Text
            {
                get
                {
                    return this._text;
                }
                set
                {
                    if (_text != value)
                    {
                        this._text = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
                    }
                }
            }


            public event PropertyChangedEventHandler PropertyChanged;
        }
    }
}

3. 修改MyPluginCommandDesigner.cs文件,让控件和属性关联。

using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Plugin;
using System;
using System.ComponentModel;
using System.Windows;

namespace MyPlugin.Designer
{
    public class MyPluginServerCommandDesigner : CommandDesigner<MyPluginServerCommand>
    {
        public override EditorSetting GetEditorSetting(PropertyDescriptor property, IBuilderCommandContext builderContext)
        {
            if (property.Name == nameof(MyPluginServerCommand.MyProperty))
            {
                return new MyEditorSetting();
            }
            return base.GetEditorSetting(property, builderContext);
        }
    }

    class MyEditorSetting : EditorSetting
    {
        public override DataTemplate GetDataTemplate()
        {
            DataTemplate template = new DataTemplate();
            FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(MyCommandPropertyEditor));
            template.VisualTree = spFactory;
            return template;
        }
        public override VerticalAlignment LabelVerticalAlignment => VerticalAlignment.Top;
    }
}

4. 效果: