在设计时显示MultilineStringEditor以编辑编辑控件的行? [英] Display a MultilineStringEditor at design-time to edit the lines of an edit-control?

查看:46
本文介绍了在设计时显示MultilineStringEditor以编辑编辑控件的行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注

有人可以向我解释如何在C#或VB.NET中做到这一点.

我被困在传递给 UITypeEditor.EditValue()方法的值上,我认为这是调用/显示编辑器的方法,但是我不确定我使用哪个值必须传递给第一个参数(它接受 IServiceProvider ITypeDescriptorContext ).我看到了 此相关答案 ,但我认为应该比创建更直接/更简便的方法一个实现 IServiceProvider ITypeDescriptorContext ...的类,因为我将运行特定的 UITypeEditor ( MultilineStringEditor ).


这是我到目前为止所得到的;当我单击编辑文本行..."(Edit Text Lines ...)操作项目时,什么也没有发生,没有任何例外,只有一无所获;我不确定这是好还是坏的信号,因为如果我尝试将其他类型的值传递给 UITypeEditor.EditValue()方法的第一个参数,那么我将得到无效类型强制转换的异常当我点击我的自定义操作项时.

C#代码版本:

 公共类MyControlActionList:DesignerActionList {私人DesignerActionUIService designerActionUISvc;公开的新MyControl组件{获取{return(MyControl)base.Component;}}公共MyControlActionList(MyControl组件):基本(组件){//缓存对DesignerActionUIService的引用,以便可以刷新DesigneractionList.this.designerActionUISvc =(DesignerActionUIService)GetService(typeof(DesignerActionUIService));}公共重写DesignerActionItemCollection GetSortedActionItems(){DesignerActionItemCollection项目=新的DesignerActionItemCollection();items.Add(new DesignerActionMethodItem(this,"EditTextLines","Edit Text Lines ...","Behavior",打开线集合编辑器",false));退换货品;}公共无效EditTextLines(){PropertyDescriptor pd = TypeDescriptor.GetProperties(this.Component)("Text");MultilineStringEditor编辑器=(MultilineStringEditor)pd.GetEditor(typeof(UITypeEditor));editor.EditValue((IServiceProvider)this.GetService(typeof(MultilineStringEditor)),this.Component.Text);}} 

VB.NET代码版本:

 公共类MyControlActionList:继承DesignerActionList私人designerActionUISvc作为DesignerActionUIServicePublic Shadows ReadOnly属性组件作为MyControl得到返回DirectCast(MyBase.Component,MyControl)结束获取最终财产Public Sub New(ByVal组件为MyControl)MyBase.New(组件)'缓存对DesignerActionUIService的引用,以便可以刷新DesigneractionList.Me.designerActionUISvc = DirectCast(GetService(GetType(DesignerActionUIService)),DesignerActionUIService)结束子公共重写函数GetSortedActionItems()作为DesignerActionItemCollection昏暗的项目作为新的DesignerActionItemCollection()items.Add(New DesignerActionMethodItem(Me,"EditTextLines","Edit Text Lines ...","Behavior",打开行集合编辑器",False))退换货品结束功能公共子EditTextLines()昏暗的pd作为PropertyDescriptor = TypeDescriptor.GetProperties(Me.Component)("Text")昏暗的编辑器为MultilineStringEditor = DirectCast(pd.GetEditor(GetType(UITypeEditor)),MultilineStringEditor)editor.EditValue(CType(Me.GetService(GetType(MultilineStringEditor)),IServiceProvider),Me.Component.Text)结束子末级 

解决方案

您要查找的编辑器是 StringArrayEditor ,用于编辑 string [] 属性.它也是 System.Design 的内部.

要在设计时使用设计器动词显示 StringArrayEditor ,您需要:

  1. 在控件中定义 string []行属性,该属性在 Text 属性中获取或设置不同的文本行.实际上,我们将编辑此属性,这将导致 Text 属性被编辑.
  2. 为了能够显示 Lines 属性的默认编辑器,请创建一个实现 ITypeDescriptorContext IServiceProvider IWindowsFormsEditorService 的类.代码>接口.这样,在获得 Lines 属性的编辑器之后,您可以调用显示所需编辑器的 EditValue 方法.
  3. 创建一个自定义 ActionList ,其中包含显示编辑器的方法.在这种方法中,应该使用在上一步中创建的类来显示属性的编辑器,并在编辑属性后,设置属性的编辑值.
  4. 为您的控件创建一个自定义设计器,并覆盖其 ActionLists 以返回您的自定义操作列表.
  5. 使用 Designer 属性装饰控件,为控件注册自定义设计器.

示例

要使该示例正常工作,将以下代码复制并粘贴到Windows Forms应用程序中的文件中就足够了.不要忘记添加对 System.Design 程序集的引用.生成项目后,可以将 MyControl 的实例拖放到窗体上,并使用智能标记窗口,可以单击 Edit Text Lines ... 链接以显示 StringArrayEditor 对话框,以编辑 Line (以及因此的 Text )属性.这是代码:

 使用系统;使用System.ComponentModel;使用System.ComponentModel.Design;使用System.Drawing.Design;使用System.Linq;使用System.Windows.Forms;使用System.Windows.Forms.Design;[Designer(typeof(MyControlDesigner))]公共类MyControl:控件{公共字符串[]行{得到{返回this.Text.Split(new string [] {Environment.NewLine},StringSplitOptions.None);}放{如果(值!=空)this.Text = string.Join(Environment.NewLine,value);}}} 

 公共类MyControlDesigner:ControlDesigner{公共重写DesignerActionListCollection ActionLists{得到{var list = new DesignerActionListCollection();list.Add(new MyControlActionList(this));返回清单;}}} 

 公共类MyControlActionList:DesignerActionList{MyControlDesigner设计器;MyControl控件{get {return(MyControl)designer.Control;}}公共MyControlActionList(MyControlDesigner设计器):基础(designer.Component){this.designer =设计师;}公共重写DesignerActionItemCollection GetSortedActionItems(){DesignerActionItemCollection项目=新的DesignerActionItemCollection();items.Add(new DesignerActionMethodItem(this,"EditTextLines",编辑文本行...",行为",打开行集合编辑器",false));退换货品;}公共无效EditTextLines(){var linesPropertyDescriptor = TypeDescriptor.GetProperties(this.Control)["Lines"];var context = new TypeDescriptionContext(this.Control,linesPropertyDescriptor);var editor =(UITypeEditor)linesPropertyDescriptor.GetEditor(typeof(UITypeEditor));var lines =(this.Control).Lines;var result =(string [])editor.EditValue(context,context,lines);如果(!result.SequenceEqual(lines))linesPropertyDescriptor.SetValue(this.Control,result);}} 

 公共类TypeDescriptionContext:ITypeDescriptorContext,IServiceProvider,IWindowsFormsEditorService{私有控制组件;私有PropertyDescriptor EditingProperty;公共TypeDescriptionContext(控件组件,PropertyDescriptor属性){this.component =组件;editingProperty =属性;}公共IContainer容器{获取{返回component.Container;}}公共对象实例{get {返回组件;}}公共无效OnComponentChanged(){var svc =(IComponentChangeService)this.GetService(typeof(IComponentChangeService));svc.OnComponentChanged(component,editingProperty,null,null);}公共布尔OnComponentChanging(){返回true;}public PropertyDescriptor PropertyDescriptor {get {return editProperty;}}公共对象GetService(Type serviceType){如果((serviceType == typeof(ITypeDescriptorContext))||(serviceType == typeof(IWindowsFormsEditorService))返回这个;返回component.Site.GetService(serviceType);}公共无效CloseDropDown(){}公共无效DropDownControl(控制控件){}DialogResult IWindowsFormsEditorService.ShowDialog(窗体对话框){IUIService服务=(IUIService)(this.GetService(typeof(IUIService)));返回service.ShowDialog(dialog);}} 

注意

您可以找到针对以下问题而提出的 ITypeDescriptorContext IServiceProvider IWindowsFormsEditorService 接口的更强大的实现:

然后在您的自定义 ActionList 类中,您可以通过以下方式显示 Lines 属性编辑器:

  EditorServiceContext.EditValue(this.designer,base.Component,"Lines"); 

RichTextBoxDesigner 中使用的方法完全相同.

I'm following this C# article to learn how to create an ActionList and Action Items, however the article is only focused to action items of type DesignerActionPropertyItem...

I would like to create an item of type DesignerActionMethodItem to call a method that must open a MultilineStringEditor to edit the text lines of the control, just the same action item that we can see in a default RichTextBox control:

Someone could explain me how to do this in C# or VB.NET?.

I'm stuck on the values to pass to the UITypeEditor.EditValue() method, I think that is the method that invokes/displays the editor, but I'm not sure which value I must pass to the first parameter (it accepts an IServiceProvider or ITypeDescriptorContext). I seen this related answer but I think there should exist a more direct/easier way than creating a class that implements IServiceProvider and ITypeDescriptorContext... since I will to run a specific UITypeEditor (MultilineStringEditor).


This is what I got so far; when I click on the "Edit Text Lines..." action item nothing happens, any exception, just nothing of nothing; I'm not sure whether that is a good or bad signal, because if I try to pass other kind of values to the first parameter of UITypeEditor.EditValue() method then I got exceptions of invalid type casting when I click on my custom action item.

C# code version:

public class MyControlActionList : DesignerActionList {

    private DesignerActionUIService designerActionUISvc;

    public new MyControl Component {
        get { return (MyControl)base.Component; }
    }

    public MyControlActionList(MyControl component) : base(component) {
        // Cache a reference to DesignerActionUIService, so the DesigneractionList can be refreshed.
        this.designerActionUISvc = (DesignerActionUIService)GetService(typeof(DesignerActionUIService));
    }

    public override DesignerActionItemCollection GetSortedActionItems() {
        DesignerActionItemCollection items = new DesignerActionItemCollection();
        items.Add(new DesignerActionMethodItem(this, "EditTextLines", "Edit Text Lines...", "Behavior", "Opens the Lines collection editor", false));
        return items;
    }

    public void EditTextLines(){
        PropertyDescriptor pd = TypeDescriptor.GetProperties(this.Component)("Text");
        MultilineStringEditor editor = (MultilineStringEditor)pd.GetEditor(typeof(UITypeEditor));

        editor.EditValue((IServiceProvider)this.GetService(typeof(MultilineStringEditor)), this.Component.Text);

    }

}

VB.NET code version:

Public Class MyControlActionList : Inherits DesignerActionList

    Private designerActionUISvc As DesignerActionUIService

    Public Shadows ReadOnly Property Component As MyControl
        Get
            Return DirectCast(MyBase.Component, MyControl)
        End Get
    End Property

    Public Sub New(ByVal component As MyControl)
        MyBase.New(component)
        ' Cache a reference to DesignerActionUIService, so the DesigneractionList can be refreshed.
        Me.designerActionUISvc = DirectCast(GetService(GetType(DesignerActionUIService)), DesignerActionUIService)
    End Sub

    Public Overrides Function GetSortedActionItems() As DesignerActionItemCollection
        Dim items As New DesignerActionItemCollection()
        items.Add(New DesignerActionMethodItem(Me, "EditTextLines", "Edit Text Lines...", "Behavior", "Opens the Lines collection editor", False))
        Return items
    End Function

    Public Sub EditTextLines()

        Dim pd As PropertyDescriptor = TypeDescriptor.GetProperties(Me.Component)("Text")
        Dim editor As MultilineStringEditor = DirectCast(pd.GetEditor(GetType(UITypeEditor)), MultilineStringEditor)

        editor.EditValue(CType(Me.GetService(GetType(MultilineStringEditor)), IServiceProvider), Me.Component.Text)

    End Sub

End Class

解决方案

The editor which you are looking for is StringArrayEditor which is used to edit string[] properties. It also is internal to System.Design.

To show StringArrayEditor at design-time using a designer verb you need to:

  1. Define a string[] Lines property in your control which gets or sets different lines of texts in Text property. In fact we will edit this property which cause the Text property getting edited.
  2. To be able to show the default editor for Lines property, create a class implementing ITypeDescriptorContext, IServiceProvider and IWindowsFormsEditorService interfaces. This way, after getting the editor of Lines property, you can call its EditValue method which shows the desired editor.
  3. Create a custom ActionList containing a method to show the editor. In this method, you should use the class which you created in previous step to show the editor for the property and after editing the property, set the edited value for property.
  4. Create a custom designer for your control and override its ActionLists to return your custom action list.
  5. Decorate the control with Designer attribute, registering your custom designer for the control.

Example

To make the example working, it's enough to copy and paste following code to a file in your Windows Forms application. Don't forget to add reference to System.Design assembly. After you build the project, you can drop an instance of MyControl on a form and using the smart tag window, you can click on Edit Text Lines... link to show StringArrayEditor dialog to edit the Line (and consequently Text) property. Here is the code:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.Design;

[Designer(typeof(MyControlDesigner))]
public class MyControl : Control
{
    public string[] Lines
    {
        get
        {
            return this.Text.Split(new string[] { Environment.NewLine },
                StringSplitOptions.None);
        }
        set
        {
            if (value != null)
                this.Text = string.Join(Environment.NewLine, value);
        }
    }
}

public class MyControlDesigner : ControlDesigner
{
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            var list = new DesignerActionListCollection();
            list.Add(new MyControlActionList(this));
            return list;
        }
    }

}

public class MyControlActionList : DesignerActionList
{
    MyControlDesigner designer;
    MyControl Control { get { return (MyControl)designer.Control; } }
    public MyControlActionList(MyControlDesigner designer) : base(designer.Component)
    {
        this.designer = designer;
    }
    public override DesignerActionItemCollection GetSortedActionItems()
    {
        DesignerActionItemCollection items = new DesignerActionItemCollection();
        items.Add(new DesignerActionMethodItem(this, "EditTextLines",
           "Edit Text Lines...", "Behavior", "Opens the Lines collection editor", false));
        return items;
    }
    public void EditTextLines()
    {
        var linesPropertyDescriptor = TypeDescriptor.GetProperties(this.Control)["Lines"];
        var context = new TypeDescriptionContext(this.Control, linesPropertyDescriptor);
        var editor =(UITypeEditor)linesPropertyDescriptor.GetEditor(typeof(UITypeEditor));
        var lines = (this.Control).Lines;
        var result = (string[])editor.EditValue(context, context, lines);
        if (!result.SequenceEqual(lines))
            linesPropertyDescriptor.SetValue(this.Control, result);
    }
}

public class TypeDescriptionContext : ITypeDescriptorContext, IServiceProvider,
    IWindowsFormsEditorService
{
    private Control component;
    private PropertyDescriptor editingProperty;
    public TypeDescriptionContext(Control component, PropertyDescriptor property)
    {
        this.component = component;
        editingProperty = property;
    }
    public IContainer Container { get { return component.Container; } }
    public object Instance { get { return component; } }
    public void OnComponentChanged()
    {
        var svc = (IComponentChangeService)this.GetService(
            typeof(IComponentChangeService));
        svc.OnComponentChanged(component, editingProperty, null, null);
    }
    public bool OnComponentChanging() { return true; }
    public PropertyDescriptor PropertyDescriptor { get { return editingProperty; } }
    public object GetService(Type serviceType)
    {
        if ((serviceType == typeof(ITypeDescriptorContext)) ||
            (serviceType == typeof(IWindowsFormsEditorService)))
            return this;
        return component.Site.GetService(serviceType);
    }
    public void CloseDropDown() { }
    public void DropDownControl(Control control) { }
    DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog)
    {
        IUIService service = (IUIService)(this.GetService(typeof(IUIService)));
        return service.ShowDialog(dialog);
    }
}

Note

You can find a more robust implementation of ITypeDescriptorContext, IServiceProvider and IWindowsFormsEditorService interfaces which I posed in response to this question:

Then in your custom ActionList class, you can show Lines property editor this way:

EditorServiceContext.EditValue(this.designer, base.Component, "Lines");

That's exactly the same way which is used in RichTextBoxDesigner.

这篇关于在设计时显示MultilineStringEditor以编辑编辑控件的行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆