cool hit counter [C#] Using IExtenderProvider to add extended properties to controls, like ToolTip_Intefrankly

[C#] Using IExtenderProvider to add extended properties to controls, like ToolTip


Affirmation.

- This article is applicable to WinForm development

- the text of“ a control (e.g. button, text box etc) (computing)” The term is used in a broad sense of wording, Generally, this includesToolStripItem、MenuItem Single interface element within, does not refer specifically to the inheritance fromControl kind of Narrow Controls

Anyone who has used the ToolTip component knows the phenomenon of dragging in a ToolTip in VS and then clicking on various controls in the form, an additional property called ToolTip will appear in its properties pane, as shown in the figure.

This article is to say of It's how to be likeToolTip thus, for the control“ extensions” Come up with an attribute( The reason for the quotation marks, It's because it's not true. of Adds a property to the control, Rather, it's in theVS It looks like that.)。 The following is illustrated by a practical example。

The demand is this of: When the user points the mouse at the menu item(ToolStripMenuItem) or Toolbar items(ToolStripButton、ToolStripLabel her kind) of length of time, (located) at Status bar tabs (ToolStripStatusLabel) shows a description of the item's function - many software do this, such as the famous Beyond Compare, as shown here.

For this effect, It's easy to think of of The practice is to provide separate information for each menu item harmony Toolbar items( hereinafter referred to asitem) registerMouseEnter harmonyMouseLeave events, (located) atenter in the event set up Status bar tabs( hereinafter referred to asviewer) ofText="item of functionalities description", (located) atleave in the eventviewer.Text=string.Empty, soonText empty; also or The person who put all ofitem of These two events are bound to two separate total ofenter harmonyleave In the event handling method, Then use the methodswitch Differentiated processing; again or -er, classifier for objects with a handleitem of functionalities description Fill in the respective ofTag in the properties, Then inenter Only one sentence is needed in the eventviewer.Text=(sender as ToolStripItem).Tag as string can then (do sth)~ Anyway, there are many ways.。 off-topic, as far as sth is concerned menu item harmony Toolbar items thus ofToolStripItem, They were born with it.ToolTipText Properties can be set up Air bubble tips, But this article does not explore whether the bubble approach or the status bar approach is better。

So is there a way, Write one likeToolTip thus of assemblies, Like callingToolDescribe, (located) atVS After dragging in the, It will be possible to find a new one initem of The properties pane has an extra pane calledDescribe of properties to, Fill in directly in theitem of functionalities description The text is finished., How nice it would be to be able to do that.:

That's bullshit., The pictures are up., Couldn't it be otherwise?。 upperToolDescribe of code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

namespace AhDung.WinForm.Controls
{
    /// <summary>
     /// Provide the extended attribute [Description] for the menu item
    /// </summary>
    [Description(" because of menu item or The control provides description Extended Properties")]
    [ProvideProperty("Describe", typeof(ToolStripItem))]
    public class ToolDescribe : Component, IExtenderProvider
    {
        /// <summary>
         /// Store the ToolStripItem served and its description
        /// </summary>
        readonly Dictionary<ToolStripItem, string> dic;

        /// <summary>
         /// Get or set the control used to display the menu item description
        /// </summary>
        [DefaultValue(null), Description(" gain or set up For displaying menu item description of a control (e.g. button, text box etc) (computing)")]
        public Component Viewer { get; set; }

        /// <summary>
         /// Create a ToolDescribe class
        /// </summary>
        public ToolDescribe()
        {
            dic = new Dictionary<ToolStripItem, string>();
        }

        /// <summary>
         /// Get menu item descriptions
        /// </summary>
        [Description(" set up menu item description")] // Although the method forGet, however, inVS The display in“ set up” It's only in line with the understanding
        [DefaultValue(null)]
        public string GetDescribe(ToolStripItem item)
        {
             // take the description of the item from the collection
            string value;
            dic.TryGetValue(item, out value);
            return value;
        }

        /// <summary>
         /// Set menu item description
        /// </summary>
        public void SetDescribe(ToolStripItem item, string value)
        {
            if (item == null) { return; }

             //If the assignment is null or string. Empty as no longer extending the ToolStripItem
            if (string.IsNullOrEmpty(value) || value.Trim().Length == 0)
            {
// Remove the item from the collection and unbind its associated events
                dic.Remove(item);
                item.MouseEnter -= item_MouseEnter;
                item.MouseLeave -= item_MouseLeave;
            }
            else
            {
                 if (!dic.ContainsKey(item))//if it is a newly added item, register its associated event
                {
                    item.MouseEnter += item_MouseEnter;
                    item.MouseLeave += item_MouseLeave;
                }

                 // Add or change the description of this item
                 dic[item] = value;//This writeup will automatically add for Keys that do not exist in the dic
            }
        }

         // mouse pointing event
        private void item_MouseEnter(object sender, EventArgs e)
        {
             // Let Viewer.Text show the description of the item
            if (Viewer is ToolStripItem) { (Viewer as ToolStripItem).Text = dic[sender as ToolStripItem]; }
            else if (Viewer is StatusBarPanel) { (Viewer as StatusBarPanel).Text = dic[sender as ToolStripItem]; }
            else if (Viewer is Control) { (Viewer as Control).Text = dic[sender as ToolStripItem]; }
        }

         //mouseover event
        private void item_MouseLeave(object sender, EventArgs e)
        {
             //clear Viewer.Text
            if (Viewer is ToolStripItem) { (Viewer as ToolStripItem).Text = string.Empty; }
            else if (Viewer is StatusBarPanel) { (Viewer as StatusBarPanel).Text = string.Empty; }
            else if (Viewer is Control) { (Viewer as Control).Text = string.Empty; }
        }

        /// <summary>
         /// Whether or not an object can have extended properties
        /// </summary>
        public bool CanExtend(object extendee)
        {
            return true;
        }
    }
}

Description of implementation.

1. Let the ToolDescribe class implement the System.ComponentModel.IExtenderProvider interface, and inherits from System.ComponentModel.Component kind, simultaneous useProvidePropertyAttribute characteristics description should kind。 realizeIExtenderProvider interface would indicate that this kind It's a【 Extensions Provider】,MSDN relevant of example:http://msdn.microsoft.com/zh-cn/library/ms229066(v=vs.80).aspx。 So what exactly is it going to give kind What properties are extended?, This is the result ofProvideProperty Characteristic Definition of, basis kind of table of contents of are【ToolStripItem】 kind Extending a program called【Describe】 of properties, So this way description[ProvideProperty("Describe", typeof(ToolStripItem))]。 succeedComponent In turn, it is intended to allowToolDescribe resembleToolTip That way you can drag in theVS In the component column, thusitem of It is only in the properties pane that there is an additionalDescribe properties to;

2、 (located) atToolDescribe kind Define a set in kind container, For storage set up up the function description ofitem and description copies。 This example uses of beDictionary<ToolStripItem, string>, obvious(ly)Key representativesitem,Value representativesitem of description copies;

3. Define a property, of type Component, to render the control for the functional description of the item, in this case the Viewer. The reason why the type is Component instead of Control is to allow the Viewer to be set as a status label (ToolStripStatusLabel), which is not a Control, so the type has to be made more "base" to increase the flexibility of the Viewer's settings.

4, implement a public string GetDescribe(ToolStripItem item) method, the role is to get the description of the specified item text, which is the reason for the definition of the container in step 2, without a container to record the individual items and their description text, this method will be difficult to implement. Note that the method must be named after the extended property name defined in Get+ProvideProperty, i.e. Describe, which together is GetDescribe. Also, adding the DefaultValue feature to the method is necessary, otherwise when dragging in a ToolDescribe, VS will extend it for all items, whether or not the Describe for an item is set, as can be seen in the InitializeComponent method.

5、 realize anpublic void SetDescribe(ToolStripItem item, string value) approach, Naming requirements as above。 this method of The role is apparently to set upitem of description copies of。 specifically realize logically, It has to do two main things:① classifier for objects with a handleitem andvalue Access to collections;② registeritem of Related events。 namely, whenitem What to do when something happens, This example is, of course, whenitem occurrenceMouseEnter harmonyMouseLeave time, Do something, So you have to register.item of These two incidents。 Speaking of which., It can actually be understood to showitem functionalities description of core realize is still based on a review of the relevant events of register, That is to say, essentially, with the mentioned above of Each is individualitem Registering events looks primitive and stupid of The way is the same of, usedToolDescribe There's nothing tall of place, It's just not that much trouble。 Of course it's here of is the application level, underlyingVS RightIExtenderProvider What the program does is naturally tall of;

6、 realize The above events of The treatment method, This example isitem_MouseEnter harmonyitem_MouseLeave, realize There's nothing to say of。 It's just up there of The code focuses on the demo realize routine, So no extras were done of Performance optimization processing, If the code is to be applied in a production environment, You need to be pairedif (Viewer is ToolStripItem) thus of Statement for processing, For example, it is possible to add the following to theViewer properties ofsetter It was recorded inViewer What kind of kind type (e.g. blood type), Then you don't have to determine each time an event is triggeredViewer kind type;

7. Finally, the only member that implements the IExtenderProvider interface: the public bool CanExtend(object extendee) method. This method is purely for VS use, the logic of the method is that when you click on a control in VS, extendee is that control and returns true then the extendee property is added in the properties pane of that control, otherwise it is not added. The answer is no, because the ProvideProperty feature is already limited to extending only the ToolStripItem class in the first place. Then the method in what case need to add logic, for example, to extend the properties for Button and TextBox, naturally ProvideProperty limited to Control more appropriate, but then, other controls that do not belong to Button and TextBox are also extended, in order not to extend them, you need to add logic in the CanExtend method return extendee is Button || extendee is TextBox, which equals whether a control will be extended or not, depending on two places, one is ProvideProperty and the other is CanExtend, the former is the first hurdle and the latter is the second;

OK, here's the set-up, and look at the results.

1、 Drag in oneToolDescribe assemblies, combine set up thatViewer because of Status bar tabs:

2、 set upitem ofDescribe properties, See figure3;

3. Run up and see.

Then again, For this effect, Passer-by if there is better than adding extended properties of The program also looks forward to teaching。

A formal one is attached below ofToolDescribe, This is better than aboveDemo Strong in, You canToolStripItem、Control、MenuItem Add extended properties, Performance optimization is also handled, Can be used in production environments。 At the same time can be seenProvideProperty Features can be superimposed, Reached to add different extended properties for different controls of table of contents of, The reason why it's not written isComponent extensionsDescribe properties, It's becauseMenuItem Only mouseover events(Select), No move-out events, To get to the point where there is no set upDescribe ofMenuItem time,Viewer.Text empty, Only for allMenuItem extensions, It's also not for thatGetDescribeOfMenuItem addDefaultValue characteristics of cause~ I don't know if the official can understand what I'm talking about, hehe。 code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;

namespace AhDung.WinForm.Controls
{
    /// <summary>
    ///  Provide function description extension properties for menu items or controls
    /// </summary>
    /// <remarks>
    /// Author:AhDung
    /// Update:201412161356, first edition
    /// </remarks>
    [Description(" Provide function description extension properties for menu items or controls")]
    [ProvideProperty("DescribeOfToolStripItem", typeof(ToolStripItem))]
    [ProvideProperty("DescribeOfControl", typeof(Control))]
    [ProvideProperty("DescribeOfMenuItem", typeof(MenuItem))]
    public class ToolDescribe : Component, IExtenderProvider
    {
        /// <summary>
        ///  Components served by the storage and their descriptions
        /// </summary>
        readonly Dictionary<Component, string> dic;

        Component viewer;
        bool viewerIsToolStripItem, viewerIsStatusBarPanel, viewerIsControl;
        ToolStripItem viewerAsToolStripItem;
        StatusBarPanel viewerAsStatusBarPanel;
        Control viewerAsControl;

        /// <summary>
        ///  Get or set the control used to display the function description
        /// </summary>
        [DefaultValue(null), Description(" Set the control used to display the function description")]
        public Component Viewer
        {
            get { return viewer; }
            set
            {
                if (viewer == value) { return; }

                viewer = value;

                viewerIsToolStripItem = false;
                viewerIsStatusBarPanel = false;
                viewerIsControl = false;

                if (viewer is ToolStripItem) { viewerIsToolStripItem = true; viewerAsToolStripItem = viewer as ToolStripItem; }
                else if (viewer is StatusBarPanel) { viewerIsStatusBarPanel = true; viewerAsStatusBarPanel = viewer as StatusBarPanel; }
                else if (viewer is Control) { viewerIsControl = true; viewerAsControl = viewer as Control; }
            }
        }

        /// <summary>
         /// Create a ToolDescribe class
        /// </summary>
        public ToolDescribe()
        {
            dic = new Dictionary<Component, string>();
        }

        /// <summary>
        ///  gainToolStripItem description
        /// </summary>
        [DefaultValue(null), Description(" Set the function description of the menu item")]
        public string GetDescribeOfToolStripItem(ToolStripItem item)
        {
            return GetDescribe(item);
        }

        /// <summary>
        ///  gainControl description
        /// </summary>
        [DefaultValue(null), Description(" Set the function description of the control")]
        public string GetDescribeOfControl(Control item)
        {
            return GetDescribe(item);
        }

        /// <summary>
        ///  gainMenuItem description
        /// </summary>
        [Description(" Set the function description of the menu item")]
        public string GetDescribeOfMenuItem(MenuItem item)
        {
            return GetDescribe(item);
        }

        // Get component description( private equity)
        private string GetDescribe(Component item)
        {
            string value;
            dic.TryGetValue(item, out value);
            return value;
        }

        /// <summary>
        ///  set upToolStripItem description
        /// </summary>
        public void SetDescribeOfToolStripItem(ToolStripItem item, string value)
        {
            if (item == null) { return; }

            if (string.IsNullOrEmpty(value) || value.Trim().Length == 0)
            {
                dic.Remove(item);
                item.MouseEnter -= item_MouseEnter;
                item.MouseLeave -= item_MouseLeave;
            }
            else
            {
                if (!dic.ContainsKey(item))
                {
                    item.MouseEnter += item_MouseEnter;
                    item.MouseLeave += item_MouseLeave;
                }

                dic[item] = value;
            }
        }

        /// <summary>
        ///  set upControl description
        /// </summary>
        public void SetDescribeOfControl(Control item, string value)
        {
            if (item == null) { return; }

            if (string.IsNullOrEmpty(value) || value.Trim().Length == 0)
            {
                dic.Remove(item);
                item.MouseEnter -= item_MouseEnter;
                item.MouseLeave -= item_MouseLeave;
            }
            else
            {
                if (!dic.ContainsKey(item))
                {
                    item.MouseEnter += item_MouseEnter;
                    item.MouseLeave += item_MouseLeave;
                }

                dic[item] = value;
            }
        }

        /// <summary>
        ///  set upMenuItem description
        /// </summary>
        public void SetDescribeOfMenuItem(MenuItem item, string value)
        {
            if (item == null) { return; }

            if (!dic.ContainsKey(item))
            {
                item.Select += item_MouseEnter;
            }

            dic[item] = value;
        }

        // Component mouse pointing event
        private void item_MouseEnter(object sender, EventArgs e)
        {
            this.SetViewerText(dic[sender as Component]);
        }

        // Component mouseover event
        private void item_MouseLeave(object sender, EventArgs e)
        {
            this.SetViewerText(string.Empty);
        }

        /// <summary>
        ///  set upViewer ofText happen to
        /// </summary>
        private void SetViewerText(string s)
        {
            if (viewerIsToolStripItem) { viewerAsToolStripItem.Text = s; }
            else if (viewerIsStatusBarPanel) { viewerAsStatusBarPanel.Text = s; }
            else if (viewerIsControl) { viewerAsControl.Text = s; }
        }

        // realizeIExtenderProvider members
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool CanExtend(object extendee)
        {
            return !(extendee is Form);
        }
    }
}

- Bunbi-


Recommended>>
1、Giving back to the cattlemen school recruitment summary from wanting to get into a bank to finally choosing the internet
2、Home applets the new dividends of the postmobile internet era
3、Introduction to jbpm 51 10
4、Python Analysis of I Am Not a Druggist Douban Review
5、ASPNETMVC5EF6EasyUI Backend Management System 67 MVC and ECharts

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号