head.WriteLine()

Montag, April 03, 2006

Komponenten mit Smart Tags veredeln

Ein nettes Feature des WinForms 2.0-Designers sind die Smart Tags. Sie fassen die wichtigsten Eigenschaften einer Komponente in übersichtlicher Form zusammen und ersparen einem die übliche Suche im Eigenschaftenfenster.
Eigene Komponenten mit einem Smart Tag zu versehen, ist relativ einfach, wenn man erst einmal die Funktionsweise der dahinter liegenden API verstanden hat. Die folgende Grafik zeigt den Aufbau:


Zunächst muss die Komponente über das Designer-Attribut auf eine von ControlDesigner abgeleiteten Klasse verweisen. Die ControlDesigner bringt nun eine ActionLists-Eigenschaft mit, die in der eigenen Designer-Klasse überschrieben werden kann. Sie gibt eine Instanz von DesignerActionListCollection zurück, die wiederum eine Instanz einer von DesignerActionList abgeleiteten Klasse enthält.
Was sich da zunächst etwas verwirrend anhört ist in der Praxis jedoch recht simpel, wie das folgende Beispiel zeigt:

Komponente:

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

namespace SimpleSmartTagDemo
{
    [Designer(typeof(LabelExDesigner))]
    class LabelEx : Label
    {
    }
}


Designer:

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

namespace SimpleSmartTagDemo
{
    internal class LabelExDesigner : ControlDesigner
    {
        private DesignerActionListCollection m_actionLists;
        
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (m_actionLists == null)
                {
                    m_actionLists = new DesignerActionListCollection();
                    m_actionLists.Add(new LabelExActionList((LabelEx)Control));
                }
                return m_actionLists;
            }
        }
    }
}


ActionList:

using System;
using System.Drawing;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;

namespace SimpleSmartTagDemo
{
    internal class LabelExActionList : DesignerActionList
    {
        private LabelEx m_labelEx;

        public LabelExActionList(LabelEx ctrl) : base(ctrl)
        {
            this.m_labelEx = ctrl;
        }

        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = new DesignerActionItemCollection();

            // Header definieren
            items.Add(new DesignerActionHeaderItem("Text"));
            items.Add(new DesignerActionHeaderItem("Farben"));
            items.Add(new DesignerActionHeaderItem("Information"));

            // Text-Eigenschaft
            items.Add(new DesignerActionPropertyItem(
                "Text",
                "Anzeigetext:",
                "Text",
                "Setzt den Anzeigetext."));

            // TextAlign-Eigenschaft
            items.Add(new DesignerActionPropertyItem(
                "TextAlign",
                "Ausrichtung:",
                "Text",
                "Setzt die Textausrichtung."));

            // ForeColor-Eigenschaft
            items.Add(new DesignerActionPropertyItem(
                "ForeColor",
                "Vordergrundfarbe:",
                "Farben",
                "Setzt die Vordergrundfarbe."));

            // BackColor-Eigenschaft
            items.Add(new DesignerActionPropertyItem(
                "BackColor",
                "Hintergrundfarbe:",
                "Farben",
                "Setzt die erste Hintergrundfarbe."));

            // Information über die Größe
            items.Add(new DesignerActionTextItem(
                "Größe: Breite = " + m_labelEx.Width.ToString() + "; Höhe = " + m_labelEx.Height.ToString(),
                "Information"));

            // Information über die Position
            items.Add(new DesignerActionTextItem(
                "Position: X = " + m_labelEx.Left.ToString() + "; Y = " + m_labelEx.Top.ToString(),
                "Information"));

            return items;
        }

        public String Text
        {
            get { return m_labelEx.Text; }
            set { this.SetPropertyValue("Text", value); }
        }

        public ContentAlignment TextAlign
        {
            get { return m_labelEx.TextAlign; }
            set { this.SetPropertyValue("TextAlign", value); }
        }

        public Color ForeColor
        {
            get { return m_labelEx.ForeColor; }
            set { this.SetPropertyValue("ForeColor", value); }
        }

        public Color BackColor
        {
            get { return m_labelEx.BackColor; }
            set { this.SetPropertyValue("BackColor", value); }
        }

        private void SetPropertyValue(String name, object value)
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(m_labelEx)[name];
            if (descriptor != null)
                descriptor.SetValue(m_labelEx, value);
            else
                throw new ArgumentException("Die gesuchte Eigenschaft konnte nicht ermittelt werden!", name);
        }
    }
}

Hierbei ist ein Verweis auf die Assembly System.Design.dll notwendig.

Das Ergebnis sieht nun in etwa so aus:



1 Comments:

  • Hallo,

    woran kann es liegen, dass die Einstelllungen im Smart Tag nur das erste Mal funktionieren? Bei zweiten umstellen, zb der ForeColor wird dies innerhalb der Oberfläche gemacht, das erzeugte Programm hat allerdings noch die zuletzt gesetzten Werte.

    MARK

    By Anonymous Mark, at Mai 05, 2006 10:18 nachm.  

Kommentar veröffentlichen

<< Home