Windows Develop Bookmark and Share   
 index > Windows Forms Designer > How to add custom attribute to member declaration using CodeDOM
 

How to add custom attribute to member declaration using CodeDOM

Problem: When adding a user defined control using the visual designer (VS 2005) I want to add a custom attribute to the variable declaration.

When implementing an user defined CodeDomSerializer one just has the opportunity to modify the code being generated within the InitializeComponent()-method but not the (member) variable declaration itself. I can't really get which code does the generation of the Designer code file itself, do I have to implement a special loader?
Beside this the visual designer generates the member variable declaration just once but I need to modify the custom attribute depending on some properties (TextKey, DefaultText, EnglishText).

Following is the code which should be generated. The additional code of interest is the custom attribute MultiLangText of the kLabel1 declaration at hte end of the code.

using Krones.MES.Multilanguage;

namespace TestApplication
{
  partial class Form1
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.kLabel1 = new Krones.MES.GUIControls.Forms.KLabel();
      this.SuspendLayout();
      // 
      // kLabel1
      // 
      this.kLabel1.TextKey = "TestTextKey";
      this.kLabel1.DefaultText = "Beispiel für einen TextKey";
      this.kLabel1.EnglishText = "Example of a text key";
      this.kLabel1.Location = new System.Drawing.Point(13, 13);
      this.kLabel1.Name = "kLabel1";
      this.kLabel1.Size = new System.Drawing.Size(41, 13);
      this.kLabel1.TabIndex = 0;
      // 
      // Form1
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(292, 273);
      this.Controls.Add(this.kLabel1);
      this.Name = "Form1";
      this.Text = "Form1";
      this.ResumeLayout(false);
      this.PerformLayout();

    }

    #endregion

    [MultiLangText("TestTextKey", "Beispiel für einen TextKey", EnglishText = "Example of a text key")]
    private Krones.MES.GUIControls.Forms.KLabel kLabel1;
  }
}



Martin Schweitzer  Friday, June 19, 2009 7:22 AM
Hi Martin,

A form uses its base class's CodeDomSerializer to serialize the controls it contains and the form itself.
Please have a try deriving a new form from the MyForm class to see if the custom CodeDomSerializer applies to the derived form.

Sincerely,
Linda Liu
Please remember to mark the replies as answers if they help and unmark them if they provide no help. end us any feedback you have about the help from MSFT at fbmsdn@microsoft.com.
Linda Liu  Monday, June 29, 2009 2:24 PM
After some research I know I have to define a serializer for the container, i.e. the form, not the control itself. This serializer has to be a TypeCodeDomSerializer.
The code now looks as follows

  [ToolboxItem(true),
  DesignerSerializer(typeof(MyFormSerializer), typeof(TypeCodeDomSerializer))]
  public class MyForm : Form
  {
  }

  internal class MyFormSerializer : TypeCodeDomSerializer
  {
    protected TypeCodeDomSerializer GetBaseComponentSerializer(IDesignerSerializationManager manager)
    {
      return (TypeCodeDomSerializer)
        manager.GetSerializer(typeof(Form), typeof(TypeCodeDomSerializer));
    }

    public override object Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
    {
      return GetBaseComponentSerializer(manager).Deserialize(manager, declaration);
    }

    public override CodeTypeDeclaration Serialize(IDesignerSerializationManager manager, object root, System.Collections.ICollection members)
    {
      TypeCodeDomSerializer baseClassSerializer = GetBaseComponentSerializer(manager);
      CodeTypeDeclaration declaration = baseClassSerializer.Serialize(manager, root, members);

      foreach (Control member in members)
      {
        ITranslateableControl translateableCtrl;
        CodeTypeMember typeMember = FindTranslateableCtrlCodeTypeMember(member, declaration.Members, out translateableCtrl);
        if (typeMember == null) { continue; }

        foreach (TranslateablePropertyInfo info in translateableCtrl.TranslateableProperties)
        {
          CodeAttributeDeclaration attrDeclaration = new CodeAttributeDeclaration(
            new CodeTypeReference(typeof(MultiLangTextAttribute)),
            new CodeAttributeArgument(new CodePrimitiveExpression(info.TextKey)),
            new CodeAttributeArgument(new CodePrimitiveExpression(info.DefaultTexts[CultureInfo.GetCultureInfo("de-DE")])));

          typeMember.CustomAttributes.Add(attrDeclaration);
        }
      }

      return declaration;
    }

    private static CodeTypeMember FindTranslateableCtrlCodeTypeMember(Control ctrl, CodeTypeMemberCollection members, out ITranslateableControl translateableCtrl)
    {
      translateableCtrl = ctrl as ITranslateableControl;
      if (translateableCtrl == null) { return null; }

      foreach (CodeTypeMember typeMember in members)
      {
        if (typeMember.Name.Equals(ctrl.Name))
        {
          return typeMember;
        }
      }

      return null;
    }
  }
Now I am able to create the CodeDOM I need. But the designer serialization seems to ignore the CustomAttributes property of the CodeTypeMember because no custom attributes are added to the member variable declaration.

Does anybody know if not all CodeDOM features are supported by visual designer or am I missing something?
Martin Schweitzer  Tuesday, June 23, 2009 3:36 PM
Hi Martin,

A form uses its base class's CodeDomSerializer to serialize the controls it contains and the form itself.
Please have a try deriving a new form from the MyForm class to see if the custom CodeDomSerializer applies to the derived form.

Sincerely,
Linda Liu
Please remember to mark the replies as answers if they help and unmark them if they provide no help. end us any feedback you have about the help from MSFT at fbmsdn@microsoft.com.
Linda Liu  Monday, June 29, 2009 2:24 PM

You can use google to search for other answers

Custom Search

More Threads

• User Controls Direct Click Access
• hosted DesignSurface - editing Controls (e.g. ComboBox) => Crash
• Looking for controls similiar to Picasa interface...
• ContextMenuStrip.items designer
• Make sort kind of DataGridViewColumns when click on HeaderColumns
• Simplest inherited control
• Handle Form.FormClosed() event
• help with vs2005 crashing because of my code
• Retrieving a combobox entry from a supplied index
• Override resize event of a Splitcontainer control