HotDog's Blog

Hotdog (Robert Verpalen) about C# and vb.net

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

JunJuly 2008Aug
SMTWTFS
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Articles

Archives

Topics

CONTACT

Fun but useful linkies

General

VS 2005

Wolfenstein ET

Smart tags are a great new option in whidbey. They make setting the default options of a control a lot quicker to do. It took me a little while to find the howto, since I was following google to msdn2, but I do believe that domain has been obsolete for quite some time now :D

The winfx.msdn contained an excellent howto however which tells all the steps needed : http://winfx.msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_fxdeveloping/html/42cc4a0c-9ab3-47e1-93b8-03b6a6ccf233.asp

However... I think I'll be using smarttags additions a lot in my own controls, but wouldn't want to go through such a setup manually each time, and include the namespaces etc. the whole charade. So time for another little wrapper class. It isn't exactly spectacular, but imho, it makes working with smarttags a lot easier. Of course everyone can make their own wrapper, but thought I share this one for those who are looking for something like it.

Code Copy HideScrollFull
using System;
using
System.Drawing;
using
System.Collections;
using
System.ComponentModel;
using
System.ComponentModel.Design;
using
System.Windows.Forms;
using
System.Text;
using
System.Reflection;


public
abstract class SmartTagList : DesignerActionList
    where ComponentType : Component
{
    private ComponentType comp;

    private DesignerActionService designerActionSvc = null;

    //The constructor associates the control
    //with the smart tag list.
    public SmartTagList(IComponent component)
        : base(component)
    {
        this.comp = component as ComponentType;

        // Cache a reference to DesignerActionService, so the
        // DesigneractionList can be refreshed.
        this.designerActionSvc =
            GetService(typeof(DesignerActionService))
            as DesignerActionService;
    }

    public ComponentType Control { get { return comp; } }

    ///
    /// Searches the ControlType object for the named property.
    /// By using a property descriptor in the set.. properties, instead
    /// of setting the ControlType object's properties directly, Visual
    /// Studio will know how to undo them.
    /// Or so the wise say ;-)
    /// Hint: using is a lot quicker ;-)
    ///

    ///
    ///
    protected PropertyDescriptor GetProperty(String propName)
    {
        PropertyDescriptor prop;
        prop = TypeDescriptor.GetProperties(comp)[propName];
        if (null == prop)
            throw new ArgumentException(
                "Property " + propName + " not found in " + typeof(ComponentType).Name);
        else
            return prop;
    }

    ///
    /// Searches the ControlType object for the named property.
    /// By using a property descriptor in the set.. properties, instead
    /// of setting the ControlType object's properties directly, Visual
    /// Studio will know how to undo them.
    /// Or so the wise say ;-)
    ///

    protected void SetValue(string PropertyName, object value)
    {
        GetProperty(PropertyName).SetValue(comp, value);
    }

    protected virtual void AddActionItems()
    {
    }

    #region
Defaults
    protected virtual bool ShowGeneralInfo
    {
        get { return false; }
    }

    protected virtual bool IncludeAnchor
    {
        get { return true; }
    }

    public AnchorStyles Anchor
    {
        get { return control.Anchor; }
        set
        {
            SetValue("Anchor", value);
        }
    }

    private Control control { get { return comp as Control; } }

    protected virtual bool IncludeText
    {
        get { return true; }
    }

    public string Text
    {
        get { return control.Text; }
        set
        {
            SetValue("Text", value);
        }
    }
    #endregion

    DesignerActionItemCollection items;

    // Implementation of this abstract method creates smart tag
    // items, associates their targets, and collects into list.
    public sealed override DesignerActionItemCollection GetSortedActionItems()
    {
        items = new DesignerActionItemCollection();

        AddActionItems();

        //control specific properties. Override the Include... properties
        //in the derrived class to turn these defaults on or off
        if (comp is Control)
        {
            if (IncludeText)
                AddProperty("Text");

            if (IncludeAnchor)
                AddProperty("Anchor");
        }

        if (ShowGeneralInfo)
        {
            AddInfo("Type: " + comp.GetType().FullName);

        }


        return items;
    }

    const string infoheader = "Component Information";

    #region
Add...
    protected void AddHeader(string Header)
    {
        items.Add(new DesignerActionHeaderItem(Header));
    }

    protected void AddProperty(string PropertyName)
    {
        AddProperty(PropertyName, PropertyName);
    }
    protected void AddProperty(string PropertyName, string DisplayText)
    {
        AddProperty(PropertyName, DisplayText, null);
    }
    protected void AddProperty(string PropertyName, string DisplayText, string Category)
    {
        AddProperty(PropertyName, DisplayText, Category, "Get/set " + PropertyName);
    }
    protected void AddProperty(string PropertyName, string DisplayText, string Category, string Description)
    {
        if (DisplayText == null) DisplayText = PropertyName;
        items.Add(new DesignerActionPropertyItem(
            PropertyName, DisplayText, Category, Description));
    }


    protected void AddText(string text)
    {
        AddText(text, null);
    }
    protected void AddText(string text, string Category)
    {
        items.Add(new DesignerActionTextItem(text, Category));
    }
    bool infoheaderadded;
    protected void AddInfo(string text)
    {
        if (!infoheaderadded)
        {
            AddHeader(infoheader);
            infoheaderadded = true;
        }
        AddText(text, infoheader);
    }


    protected void AddMethod(string MethodName)
    {
        AddMethod(MethodName, null);
    }
    protected void AddMethod(string MethodName, string DisplayText)
    {
        AddMethod(MethodName, DisplayText, null);
    }
    protected void AddMethod(string MethodName, string DisplayText, string Category)
    {
        AddMethod(MethodName, DisplayText, Category, null);
    }
    protected void AddMethod(string MethodName, string DisplayText, string Category, string Description)
    {
        if (DisplayText == null) DisplayText = MethodName;
        items.Add(new DesignerActionMethodItem(this, MethodName, DisplayText, Category, Description));
    }
    #endregion

}

. . .
Derriving classes can override the AddActionItems method to, well add action items. But instead of needing to add the entire actionlist.Add(new DesignerAction...Item(..,...) , the wrapper has a bunch of Add... (AddMethod,AddProperty,etc) method that make that process a bit quicker and easier on the eye.
Code Copy HideScrollFull
    public class TestActionList : SmartTagList<Test>
    {

        public TestActionList(IComponent component)
            : base(component) //unfortunately, could not wrap away the need of the constructor call :(
        {

        }

        public void TestVoid()
        {
            MessageBox.Show("Hello");
        }


        private int anint;
        public int SomeInteger
        {
            get { return anint; }
            set { anint = value; }
        }

        protected override void AddActionItems()
        {
            AddMethod("TestVoid");
            AddProperty("SomeInteger", "An integer");
            AddInfo("You can add info here");
        }
    }
. . .
Assigning the actionlist to a designer still has to be done in the same way as in the article mentioned in the top (unless you have your own base designer classes ;-) )
In this case that would look something like:
Code Copy HideScrollFull
    public class TestDesigner : System.Windows.Forms.Design.ControlDesigner
    {
        DesignerActionListCollection actionLists;

        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (null == actionLists)
                {
                    actionLists = new DesignerActionListCollection();
                    actionLists.Add(
                        new TestActionList(this.Component));
                }
                return actionLists;
            }
        }
    }

    [Designer(typeof(TestDesigner))]
    public class Test : TextBox
    {

    }
. . .
All in all those tags were a great idea of the designers of Whidbey and some versions further there might be easier wrappers build in, but for now this one will do for me (with the extra help of a custom base Designer class ;-) )
posted on Friday, September 02, 2005 1:19 AM