如何在自定义UserControl(.Net 4,Winforms)上使用项目集合编辑器? [英] How to use an Items Collection Editor on a custom UserControl (.Net 4, Winforms)?

查看:79
本文介绍了如何在自定义UserControl(.Net 4,Winforms)上使用项目集合编辑器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个包含自定义ToolStrip控件的UserControl.

在整个应用程序中使用UserControl时,由于逻辑上嵌入在UserControl中,因此无法直接访问ToolStrip控件.因此,为了访问ToolStrip的项目,我在UserControl类中定义了一个只读属性,该属性返回ToolStrip的项目.

现在,可以使用UserControl.Items属性以编程方式编辑ToolStrip的项目,但是在设计模式下我不能做同样的事情.就像有人将UserControl从ToolBox拖动到窗体,转到属性网格,选择Items属性并相应地处理根深蒂固的ToolStrip的项目一样;就像我们在Items Collection Editor的帮助下处理任何标准ToolStrip控件的items集合一样.

在此,尽管UserControl的Items属性显示在属性网格中,但它不可用,并且每次单击时,它都会显示一条错误消息-值不能为null.参数名称:值''.我确定这是因为该属性被声明为只读,并且我需要进行更多加倍操作,以便在属性网格中单击该属性时,Items Collection Editor会弹出并带有ToolStrip的项目,因此可以对其进行处理.

那我应该怎么做呢?

请注明我是否不清楚.

问候!

I created a UserControl that contains a custom ToolStrip Control.

While using the UserControl throughout an application, the ToolStrip control cannot be accessed directly, as logically it''s embedded in the UserControl. So, to access the items of the ToolStrip I defined a readonly property in the UserControl class that returns the items of the ToolStrip.

Now programmatically the items of the ToolStrip can be edited by using the UserControl.Items property, but I cannot do the same in the design mode. Like someone drags the UserControl from the ToolBox to the form, goes to the property grid, chooses the Items property and manipulates the items of the ingrained ToolStrip accordingly; just as we do with any standard ToolStrip control''s items collection with the help of Items Collection Editor.

Herein, though the Items property of the UserControl shows in the property grid, it''s not usable and every time I click, it shows an error message- ''Value cannot be null. Parameter name: value''. I''m sure this is because the property is declared just as readonly and I need to hike more so that when it is clicked in the property grid, the Items Collection Editor pops up with the items of the ToolStrip and can be handled consequently.

So how should I be doing this?

Please state if I''m not clear.

Regards!

推荐答案

我认为您甚至不需要公开用户控件的子级,工具条项等.它可以工作,但这仍然是违反适当的封装.对于真正准确的工作,您应该更好地公开单独的事件和属性.这是想法:
I don''t think you need to expose even the user control children, tool strip items, etc. It can work, but this is still a violation of proper encapsulation. For really accurate work, you should better expose separate events and properties. Here is the idea:
public class MyControl : UserControl {

   public MyControl() {
       //...
       toolStrip.Items.Add(toolStripButtonViewSource); // in real life, not directly placed here, this is just for explanation of the idea
       toolStripButtonViewSource.Click += (sender, eventArgs) => {
           if (ViewSourceRequested != null)
               ViewSourceRequested.Invoke(toolStripButtonViewSource, new System.EventArgs());
       };
       //...
   } //MyControl
 
   public event System.EventHandler ViewSourceRequested;

   public System.Drawing.Color ViewSourceButtonBackColor {
       get { return toolStripButtonViewSource.BackColor; }
       set { toolStripButtonViewSource.BackColor = value; }
   } //ViewSourceButtonBackColor

   public System.Drawing.Image ViewSourceButtonBackgroundImage {
       get { return toolStripButtonViewSource.BackgroundImage; }
       set { toolStripButtonViewSource.BackgroundImage = value; }
   } //ViewSourceButtonBackgroundImage
   
   //... and so one, for every feature you want to expose, for every item

   ToolStripButton toolStripButtonViewSource = //...

} //MyControl



可能有点机械"工作,但是通过这种方式,您只公开您真正想要公开的内容,就可以隐藏内部功能.

—SA



Could be a bit too much "mechanical" work, but in this way you only expose what you really want to expose, can hide internal functionality.

—SA


我不是WinForms的专家,因为多年来没有使用它们,但是我相信您需要做的就是创建一个自定义控件.请参阅以下内容,它可能会有所帮助:创建自定义控件-提供设计时间支持1 [ ^ ]
I am not an expert on WinForms since have not used them in years, but I beleive what you need to do is create a custom control. See the following, it might help: Creating Custom Controls-Providing Design Time Support 1[^]


您好!
我已经在这个问题上工作了一段时间,而我得到的两个最广泛的想法是:
1)将ToolStrip公开为属性.
2)将ControlDesigner用于UserControl,并为ToolStrip设置EnableDesignMode.

但是不知何故,它们实际上都没有达到我的目的,因为暴露ToolStrip会让用户完全控制它,这不是我的目标.第二个选项甚至会使用户不得不删除ToolStrip.因此,我不得不找出一种不同的方法.那是我绊倒CollectionBase类的时候.

就像说的那样,CollectionBase类是强类型集合的抽象基类.那么如何通过它维护ToolStrip项目集合呢?
我创建了CollectionBase类的实例,并通过它管理ToolStrip项的添加,修改,获取和删除.集合中的每个项目均来自从ToolStripButton类继承的类.这样,单个项目可以作为任何标准ToolStripButton处理,并且您可以相应地向用户隐藏或显示属性.最后,将有问题的ToolStrip设置为CollectionBase的父级,该CollectionBase最终也将成为每个ToolStripItem的父级.这是概念:

Hi there!
I have been working on the issue for a while, and the two most widely held ideas I got are:
1) Exposing the ToolStrip as a property.
2) Use a ControlDesigner for the UserControl and set EnableDesignMode for the ToolStrip.

But somehow none of them actually served my purpose, as exposing the ToolStrip would let the user have full control on it, which was not my objective. The second option would even put the user up with deleting the ToolStrip. Hence I had to figure out a different approach. That''s when I tripped upon the CollectionBase class.

As it says, the CollectionBase class is the abstract base class for a strongly typed collection. So how about maintaining the ToolStrip item collection through it?
I created an instance of the CollectionBase class and regulated the addition, modification, fetching and deletion of the ToolStrip items through it. Each item in the collection hails from a class that is inherited from the ToolStripButton class. In that way, individual item can be handled as any standard ToolStripButton and you can hide or show the properties to the user accordingly. Lastly, the ToolStrip in question is set as the parent of the CollectionBase which eventually becomes the parent of each ToolStripItem too. Here''s the concept:

Imports System.ComponentModel
Imports System.Windows.Forms
Imports Office2003
Imports System.Drawing
Imports System.Windows.Forms.Design

Public Class MyUserControl
    Private _Buttons As MyUserControlButtons
    Public Event MyUserControlButtonClicked(ByVal Sender As MyUserControlButton)

    Public Sub New()
        MyBase.New()

        'This call is required by the Component Designer.
        InitializeComponent()

        _Buttons = New MyUserControlButtons(MyToolStrip)
    End Sub

    <designerserializationvisibility(designerserializationvisibility.content)> _
    Public ReadOnly Property Buttons As MyUserControlButtons
        Get
            Return _Buttons
        End Get
    End Property

    Private Sub MyToolStrip_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles MyToolStrip.ItemClicked
	 'Check if the ToolStrip item clicked is a ToolStripButton...
        If TypeOf e.ClickedItem Is ToolStripButton Then
            'Insert your code here...

	     'Raise the custom event.
            RaiseEvent MyUserControlButtonClicked(Item)
        End If
    End Sub
End Class

#Region "Manager classes for MyUserControl buttons."
 
Public Class MyUserControlButtons
    Inherits CollectionBase
    Private _Parent As ToolStrip

    Public Sub New(ByVal Holder As ToolStrip)
        MyBase.New()
        _Parent = Holder
    End Sub

    Public ReadOnly Property Parent() As ToolStrip
        Get
            Return _Parent
        End Get
    End Property

    Default Public ReadOnly Property Item(ByVal Index As Integer) As MyUserControlButton
        Get
            Return CType(List(Index), MyUserControlButton)
        End Get
    End Property

    Public Function Add() As MyUserControlButton
        Return Me.Add
    End Function

    Public Sub Add(ByVal Value As MyUserControlButton)
        List.Add(Value)
        Value.Parent = Me.Parent
    End Sub

    Public Function Add(ByVal Name As String, ByVal Image As Image) As MyUserControlButton
        Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
        b.Name = Name
        b.Text = Name
        b.Image = Image
        Me.Add(b)
        Return b
    End Function

    Public Function Add(ByVal Name As String, ByVal Text As String, ByVal Image As Image) As MyUserControlButton
        Dim b As MyUserControlButton = New MyUserControlButton(Me.Parent)
        b.Name = Name
        b.Text = Text
        b.Image = Image
        Me.Add(b)
        Return b
    End Function

    Public Sub Remove(ByVal Value As MyUserControlButton)
        List.Remove(Value)
    End Sub

    Public Function IndexOf(ByVal Value As Object) As Integer
        Return List.IndexOf(Value)
    End Function

    Public Function Contains(ByVal Value As MyUserControlButton) As Boolean
        Return List.Contains(Value)
    End Function

    Protected Overrides Sub OnInsertComplete(ByVal index As Integer, ByVal value As Object)
        Dim b As MyUserControlButton = CType(value, MyUserControlButton)
        b.Parent = Me.Parent
        Me.Parent.Items.Insert(index, CType(value, ToolStripButton))
        MyBase.OnInsertComplete(index, value)
    End Sub

    Protected Overrides Sub OnSetComplete(ByVal index As Integer, ByVal oldValue As Object, ByVal newValue As Object)
        Dim b As MyUserControlButton = CType(newValue, MyUserControlButton)
        b.Parent = Me.Parent
        MyBase.OnSetComplete(index, oldValue, newValue)
    End Sub

    Protected Overrides Sub OnClearComplete()
        MyBase.OnClearComplete()
    End Sub
End Class

Public Class MyUserControlButton
    Inherits ToolStripButton

    Sub New()
        MyBase.New()
        Init()
    End Sub

    Sub New(ByVal Holder As ToolStrip)
        MyBase.New()
        Init()
        Me.Parent = Holder
    End Sub

    Private Sub Init()
        Me.AutoToolTip = False
        Me.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
        Me.ImageAlign = ContentAlignment.MiddleLeft
        Me.ImageIndex = -1
        Me.ImageKey = ""
        Me.ImageTransparentColor = Color.Magenta
        Me.TextAlign = ContentAlignment.MiddleLeft
        Me.TextDirection = ToolStripTextDirection.Horizontal
    End Sub

    <browsable(false),>
    EditorBrowsable(False)> _
    Public Shadows Property AccessibleDefaultActionDescription As String
        Get
            Return MyBase.AccessibleDefaultActionDescription
        End Get
        Set(ByVal value As String)
            MyBase.AccessibleDefaultActionDescription = value
        End Set
    End Property

    <browsable(false),>
    EditorBrowsable(False)> _
    Public Shadows Property AccessibleDescription As String
        Get
            Return MyBase.AccessibleDescription
        End Get
        Set(ByVal value As String)
            MyBase.AccessibleDescription = value
        End Set
    End Property

    <browsable(false),>
    EditorBrowsable(False)> _
    Public Shadows Property AccessibleName As String
        Get
            Return MyBase.AccessibleName
        End Get
        Set(ByVal value As String)
            MyBase.AccessibleName = value
        End Set
    End Property


    ' Keep on hiding the irrelevant properties...


    <defaultvalue(false)> _
    Public Shadows Property AutoToolTip As Boolean
        Get
            Return MyBase.AutoToolTip
        End Get
        Set(ByVal value As Boolean)
            MyBase.AutoToolTip = value
        End Set
    End Property

    <defaultvalue(gettype(toolstripitemdisplaystyle),> _
    Public Overrides Property DisplayStyle As System.Windows.Forms.ToolStripItemDisplayStyle
        Get
            Return MyBase.DisplayStyle
        End Get
        Set(ByVal value As System.Windows.Forms.ToolStripItemDisplayStyle)
            MyBase.DisplayStyle = value
        End Set
    End Property

    Public Overrides Property Image() As Image
        Get
            Return MyBase.Image
        End Get
        Set(ByVal value As Image)
            MyBase.Image = value
        End Set
    End Property

    <defaultvalue(gettype(contentalignment),> _
    Public Shadows Property ImageAlign As ContentAlignment
        Get
            Return MyBase.ImageAlign
        End Get
        Set(ByVal value As ContentAlignment)
            MyBase.ImageAlign = value
        End Set
    End Property

    <editorbrowsable(false),>
    DefaultValue(-1)> _
    Public Shadows Property ImageIndex As Integer
        Get
            Return MyBase.ImageIndex
        End Get
        Set(ByVal value As Integer)
            MyBase.ImageIndex = value
        End Set
    End Property

    <editorbrowsable(false),>
    DefaultValue("")> _
    Public Shadows Property ImageKey As String
        Get
            Return MyBase.ImageKey
        End Get
        Set(ByVal value As String)
            MyBase.ImageKey = value
        End Set
    End Property

    Public Shadows Property ImageTransparentColor As Color
        Get
            Return MyBase.ImageTransparentColor
        End Get
        Set(ByVal value As Color)
            MyBase.ImageTransparentColor = value
        End Set
    End Property

    Public Shadows Property Name() As String
        Get
            Return MyBase.Name
        End Get
        Set(ByVal value As String)
            MyBase.Name = value
        End Set
    End Property

    <browsable(false)> _
    Public Shadows Property Parent As ToolStrip
        Get
            Return MyBase.Parent
        End Get
        Set(ByVal value As ToolStrip)
            MyBase.Parent = value
        End Set
    End Property

    Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(ByVal value As String)
            MyBase.Text = value
        End Set
    End Property

    <defaultvalue(gettype(contentalignment),> _
    Public Overrides Property TextAlign As ContentAlignment
        Get
            Return MyBase.TextAlign
        End Get
        Set(ByVal value As ContentAlignment)
            MyBase.TextAlign = value
        End Set
    End Property

    <browsable(false),>
    EditorBrowsable(False),
    DefaultValue(GetType(ToolStripTextDirection), "Horizontal")> _
    Public Overrides Property TextDirection As ToolStripTextDirection
        Get
            Return MyBase.TextDirection
        End Get
        Set(ByVal value As ToolStripTextDirection)
            MyBase.TextDirection = value
        End Set
    End Property


    ' Define other properties accordingly...
End Class

#End Region



MyUserControl是包含名为MyToolStrip的ToolStrip的自定义用户控件. MyUserControlButtons是从CollectionBase继承的类,而MyUserControlButtons的每个项目都是从ToolStripButton继承的MyUserControlButton类的对象.

在MyUserControl的构造函数中,将MyUserControlButtons实例化为MyToolStrip作为其父项.通过从MyUserControlButton创建新对象,将项目添加到MyUserControlButtons.隐藏或显示的项目的属性在MyUserControlButton中管理.
MyUserControl通过只读属性按钮"返回按钮列表.请注意按钮"属性的DesignerSerializationVisibility属性.它指定在设计时在组件上序列化属性时要使用的持久性类型. 内容"枚举成员告诉代码生成器为对象的内容而不是对象本身生成代码.

这种方法的缺点是,在UserControl上执行复制粘贴操作时,无法保留ToolStrip的项目.仅当项目由用户显式处理时才对内容进行序列化,而在复制粘贴期间则不进行序列化.任何有关如何处理它的想法都将受到高度赞赏.

感谢所有海报.尽管我采用了自己的概念,但您的想法为我铺平了道路.



MyUserControl is the custom user control containing the ToolStrip named MyToolStrip. MyUserControlButtons is the class that inherits from CollectionBase and each item of MyUserControlButtons is an object of MyUserControlButton class that inherits from ToolStripButton.

In the constructor of MyUserControl, MyUserControlButtons is instantiated with MyToolStrip as its parent. Items are added to MyUserControlButtons by creating new objects from MyUserControlButton. Properties of the items to be hidden or shown are managed in MyUserControlButton.
MyUserControl returns the list of the buttons through the read only property ''Buttons''. Note the DesignerSerializationVisibility attribute of the ''Buttons'' property. It specifies the type of persistence to use when serializing a property on a component at design time. The ''Content'' enumeration member tells the code generator to produce code for the contents of the object, rather than for the object itself.

The drawback in this approach is that you cannot retain the items of the ToolStrip while performing copy-paste on the UserControl. It serializes the contents only when items are handled explicitly by the user but not during copy-paste. Any idea of how to deal with it is highly appreciated.

Thanks to all posters. Though I applied my own concept, your ideas paved my way.


这篇关于如何在自定义UserControl(.Net 4,Winforms)上使用项目集合编辑器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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