ホーム > 設計時Silverlightの Silverlightツールキットで>デザイン時の機能の実装

Silverlightツールキットの設計時の機能の実装

はじめ

これは私のSilverlightのデザイン時機能のシリーズの第二の投稿です。 最初の投稿のSilverlightツールキットの設計時の機能の設計時の機能を示したのSilverlight Toolkitのコントロールを。 この記事は、どのように実装されるかを説明します。 うまくいけばこの記事は、Silverlightのデザイン時の機能を実装する方法を示す、私たちのソースコードを説明し、フレームワークを提供し、ソースコードの読者が自分のプロジェクトで直接使用できることができます。

概要

"Silverlightのツールキット-バイナリ、サンプル、ドキュメント、ユニットテストとソース"ダウンロードの2008年12月リリース 、Visual Studioで開いSourceSilverlight.Controls.slnを、そして我々は、デザインのソリューションフォルダの下に12のデザインプロジェクトがあることをそれぞれ制御するための3つが表示されます。アセンブリ。

Visual StudioでSilverlight.Controls.sln

コントロールの例のためのプロジェクトを行う、3つの設計プロジェクトがあります。

  • Controls.Design:Visual StudioとExpression Blendの両方で共有される、設計時の機能が含まれているビルドのWindows.Controls.Design.dll、。
  • Controls.Expression.Design:のみのExpression Blendのデザイン時の機能が含まれているビルドのWindows.Controls.Expression.Design.dll、。
  • Controls.VisualStudio.Design:のみのVisual Studioのデザイン時の機能が含まれているビルドのWindows.Controls.VisualStudio.Design.dll、。

Extensions.csとMetadataBase.cs、すべての設計プロジェクトで共有されています:2つのファイルが含まれてDesign.Commonのフォルダもあります。

それは非常には、ジャスティンエンジェルのブログの記事読むことをお勧めします。 Silverlightのデザイン時拡張機能を :それは、以下の実装の ​​ベースとなっているのSilverlightのデザインタイム拡張性、で良いの背景/概要情報を提供します。

プロジェクト

全12デザインのプロジェクトが同じ実装パターンに従うので、私はそれらすべてを説明するためにControl.Designプロジェクトを使用します。

初めてのVisual Studioにソースディレクトリの下にSilverlight.Controls.slnをロードし、我々は以下のような画面が表示されます。

Visual StudioでSilverlight.Controls.Design.csproj

  • Controls.Designは、コントロールのプロジェクトでプロジェクトの依存関係を持っています。 この依存関係は、コントロールのプロジェクトを最初にビルドされるように、とControls.Designはコントロールのプロジェクトで構築Microsoft.Windows.Controlsアセンブリへの参照を持っています。 デザイン時のアセンブリは、常に参照するランタイムのアセンブリは、それがために、設計時の機能を提供します。
  • ディレクトリ%DevEnvDir%のPublicAssemblies(:私のラップトップ上のプログラムFilesMicrosoftのVisual Studio 9.0Common7IDEPublicAssemblies c)に基づくが、どちらもControls.Design参照のMicrosoft.Windows.Design&Microsoft.Windows.Design.Extensibilityアセンブリ、。 デザイナの機能拡張フレームワークを提供するデザイン時のアセンブリには、多くの場合、参照は、これら2つのアセンブリを、。 メタデータ属性(CategoryAttribute、DescriptionAttributeとのような)の多くが定義されているSystem.ComponentModel名前空間が含まれてあまりにもデザイン時のアセンブリを常に参照するシステムの組み立て、、。
  • Controls.Design参照System.Windowsアセンブリ。 我々はあまりにもControls.Design.csprojの参照を見ることができます。

    <reference Include="System.Windows, Version=2.0.5.0、Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
    <SpecificVersion>偽</ SpecificVersion>
    <HintPath> .. BinariesSystem.Windows.dll </ HintPath>
    <Private>偽</プライベート>
    </参照>

    注意してください:

    • Control.Designは、Windowsクラスライブラリプロジェクトではなく、Silverlightプロジェクトであり、生成されたMicrosoft.Windows.Controls.Design.dllは、Visual StudioやExpression Blendのではなく、内部で実行されるSilverlightのアセンブリのようなデザイナーの内側のデスクトップ上で実行NETアセンブリです。 Microsoft.Windows.Controls.Design.dllがSilverlightランタイムのアセンブリMicrosoft.Windows.Controls.dllのためのデザイン時のアセンブリであってもブラウザ、。
    • 参照されるSystem.Windows名前アセンブリは、実際にはSilverlightのアセンブリ(バージョン2.0.5.0)です。 System.Windowsアセンブリは、Silverlightコントロールのすべての設計プロジェクトで必要とされていない可能性があります。 我々が主な原因GetMemberName <T>からここにそれを必要とする(式<のFunc <T, object>は> exprは)我々はより多くの記事の後半で議論するというExtension.csの方法。 私たちはすぐにわかるように。NETおよびSilverlightの参照のミックスは、興味深い問題のすべての種類を作成します。

      。ILDASMのスクリーンショットの下にMicrosoft.Windows.Controls.Design.dllでNETおよびSilverlightのアセンブリへの参照が混用さを示しています。
      ILDASM Microsoft.Windows.Controls.Design.dll Microsoft.Windows.Controls.Designアセンブリマニフェスト

      • 。版2:0:21024:1838 Silverlightツールキット2008年12月リリースのバージョン番号です。
      • 。版3:5:0:0。NET Framework 3.5用のバージョン番号です。
      • 。版2:0:0:0のSilverlight 2.0のバージョン番号です。
    • 、あまりにもプロジェクトウィンドウでSystem.Windows名前アセンブリの参照の横に警告を"参照コンポーネント'System.Windows'が見つかりませんでした"、およびエラー一覧]ウィンドウには、最初のロードControls.DesignのプロジェクトをVisu​​al Studioにする場合があります。 。Controls.Design代わりにSilverlightのNETのプロジェクトである、と我々はSilverlightがインストールされている場所が不明なためです(これはCの下にある:私のラップトップ上で、およびCの下でプログラムFilesMicrosoft Silverlight2.0.31005.0:プログラムファイル(X86私のデスクトップ上でマイクロソフトSilverlight2.0.31005.0)。 解決策は、ビルド前のイベントのSilverlightのインストール方向からにSystem.Windows.dllをコピーするコマンド.. CopySystemWindows.bat ..バイナリを持つことです。 プロジェクトを構築したので、一度我々はすぐに見るように、警告は、離れて行きます。
  • 初めてのVisual StudioにControls.DesignのプロジェクトをロードするときにVisual Studioのスクリーンショット上の例では、プロジェクトの未亡人でファイルのMicrosoft.Windows.Controls.XML隣に別の警告サインは、そこです。 > [ビルド]タブ、オプション"XMLドキュメントファイル"がチェックされている、と".. Binarのパスを持っています - このファイルは、コントロールのプロジェクトのプロパティにあるため、依存性のコントロールのプロジェクトを構築することによって生成されます。
    iesMicrosoft.Windows.Controls.XML"あなたがControls.Designのプロジェクトをビルドする場合、我々はすぐに見るように、警告は、離れて行く。
  • Controls.DesignプロジェクトはMetadata.csファイルを持っており、Design.Commonフォルダ内のExtension.csとMetadataBase.csへのリンク。 全12デザインプロジェクトは、これら3つのファイルがあります。 我々は、後でより詳細に説明します。

Controls.Designのプロジェクトまたはソリューション全体をビルド、我々が見ることができる。

Silverlight.Control.slnの出力を構築する

  • すべてのプロジェクトはエラー0と警告0で問題なく構築。
  • System.Windows基準とMicrosoft.Windows.Controls.XMLファイルの横に警告サインが消えた。
  • ビルドプロセスのコード分析に長い時間がかかり、それは2つの警告を生成します。 最初、CA0060は、混在。NETおよびSilverlightの参照とExtension.csのコードの別の問題です。 再度SourceBinariesディレクトリおよび建物へのSilverlightのインストールディレクトリからSystem.dllのとSystem.Core.dllをコピーすることで警告を取り除くことができます。

MetadataBase.cs

MetadataBase.csは、一緒にMetadata.csで、設計時のメタデータを登録するためのフレームワークを実装します。

  • DescriptionAttributesは、​​自動的にソースコード内の"/ / / <summary>"XMLドキュメントコメントから公共のコントロールクラス(すなわち、FrameworkElementのサブクラス)とその公開プロパティに対して生成されます。 (グッドコメント支払う! :-)
  • デザイナーからコントロールクラスを非表示にするには、プロジェクトのMetadata.csファイルでAddAttributesメソッドに以下のような行を追加します。
    builder.AddCallback(typeof演算(のTreeViewItem)、B => b.AddCustomAttributes(新しいToolboxBrowsableAttribute(偽)));
  • コントロールクラスの他のカスタム属性を登録するには、後述するViewboxMetadata.csのように、プロジェクトにXxxMetadata.csファイルを追加します。

あなたがフレームワークが好きなら、あなたは対象、直接あなた自身のプロジェクトでMetadataBase.csとMetadata.csを使用することができますマイクロソフトPublic Licenseのすべてのソースファイルの先頭に含ま。

MetadataBase.cs:

  / /(C)著作権Microsoft Corporationの。
 / /このソースMicrosoftパブリックライセンス(Ms - PL)の対象となります。
 / /詳細については、http://go.microsoft.com/fwlink/?LinkID=131993を参照してください。
 / /他のすべての権利を保有。

システムを使用して;
 System.Collections.Genericを使用して、
 System.ComponentModelを使用して、
 System.Diagnosticsを使用して
 System.Diagnostics.CodeAnalysisを使用して、
は、System.Globalizationを使用して、
します。using System.IO;
 System.Linqのを使用して、
 System.Linq.Expressionsを使用して、
 します 。using System.Reflection;
 System.Windowsを使用して、
 System.Xml.Linqを使用して、
 Microsoft.Windows.Design.Metadataを使用して、

 名前空間 Microsoft.Windows.Controls.Design.Common
 {
     / / / <summary>
     / / / MetadataRegistrationクラス。
     / / / </概要>
     パブリッククラス MetadataRegistrationBase
     {
         / / / <summary>
         / / /設計時のメタデータ属性テーブルを構築します。
         / / / </概要>
         / / / <returns>カスタム属性テーブル。</リターン>
         保護された仮想 AttributeTable BuildAttributeTable()
         {
             AttributeTableBuilderビルダーは= 新しい AttributeTableBuilder();

             AddDescriptions(ビルダー);
             AddAttributes(ビルダー);
             AddTables(ビルダー);

             builder.CreateTable()を返す
         }

         / / / <summary>
         / / /アセンブリ内のすべてのAttributeTableBuilderのサブクラスを検索
         / / /とアセンブリの属性テーブルにその属性を追加します。
         / / / </概要>
         / / / <param name="builder">アセンブリの属性テーブルビルダ。</ PARAM>
         , Justification = "Design time dll should not fail!" )] [SuppressMessage("Microsoft.Design"、"CA1031:DoNotCatchGeneralExceptionTypes"、ジャスティフィケーション="!デザイン時のdllが失敗しない")]
         プライベート静的ボイド AddTables(AttributeTableBuilderビルダー)
         {
             ); Debug.Assertの(!ビルダー= nullを 、"AddTablesはnullパラメータで呼び出されます!");

            アセンブリのasm = Assembly.GetExecutingAssembly();
             asm.GetTypes()) foreachの (asm.GetTypes タイプT())
             {
                 (AttributeTableBuilder))) 場合(t.IsSubclassOf(typeof演算 (AttributeTableBuilder)))
                 {
                     
                     {
                         AttributeTableBuilder ATB =(AttributeTableBuilder)Activator.CreateInstanceを(T);
                         builder.AddTable(atb.CreateTable());
                     }
                     キャッチ (例外電子)
                     {
                         .Format(CultureInfo.InvariantCulture, "Exception in AddTables method: {0}" , e)); Debug.Assertの( 偽の文字列フォーマット(CultureInfo.InvariantCulture、"AddTablesメソッドで例外:{0}"。、E));
                     }
                 }
             }
         }

         / / / <summary>
         / / /組み込みのXMLファイルの大文字と小文字を区別するリソースの名前を取得または設定します。
         / / / </概要>
         保護された文字列の XmlResourceName {取得または設定します。}

         / / / <summary>
         / / /型'アセンブリ修飾名のアセンブリのFullNameを取得または設定します。
         / / / </概要>
         保護された文字列の AssemblyFullName {取得または設定します。}

         / / / <summary>
         / / /実行時 ​​にアセンブリのXMLファイルからdescription属性を作成します。
         / / / </概要>
         / / / <param name="builder">アセンブリの属性テーブルビルダ。</ PARAM>
         , Justification = "Design time dll should not fail." )] [SuppressMessage("Microsoft.Design"、"CA1031:DoNotCatchGeneralExceptionTypes"、ジャスティフィケーション="設計時のDLLが失敗ではないはず。")]
         プライベートボイド AddDescriptions(AttributeTableBuilderビルダー)
         {
             ); Debug.Assertの(!ビルダー= nullを 、"AddDescriptionsはnullパラメータで呼び出されます!");

             .IsNullOrEmpty(XmlResourceName) || 場合文字列 IsNullOrEmpty(XmlResourceName)。| |
                 文字列 。IsNullOrEmpty(AssemblyFullName))
             {
                 リターン ;
             }

             XDocumentをxdoc = XDocument.Load( 新しいStreamReader(
                 。Assembly.GetExecutingAssembly()GetManifestResourceStream(XmlResourceName)));
             ) (xdoc == nullの場合
             {
                 リターン ;
             }

             xdoc.Descendants( "member" )) foreachの (xdoc.Descendants のXElementのメンバー("メンバー"))
             {
                 
                 {
                     )member.Attribute( "name" ); 文字列名=( 文字列 )member.Attribute("名前");
                     , StringComparison.OrdinalIgnoreCase); ブール値 = name.StartsWith("T:"、StringComparison.OrdinalIgnoreCaseを)isType。
                     (isType 場合 | |
                         name.StartsWith("P:"、StringComparison.OrdinalIgnoreCase))
                     {
                         int型 lastDot = name.Length;
                         文字列 typeNameは、
                         場合 (isType)
                         {
                             typeNameは= name.Substring(2);
                         }
                         
                         {
                             lastDot = name.LastIndexOf('。');
                             typeNameは= name.Substring(2、lastDot - 2);
                         }
                         typeNameは+ = AssemblyFullName;

                        型t = Type.GetType(typeNameは);
                         && t.IsPublic && t.IsClass && 場合 (T!= NULL&&t.IsPublic&t.IsClass&&
                             t.IsSubclassOf(typeof演算 (FrameworkElementが)))
                         {
                             ).FirstOrDefault().Value; 。。 文字列 DESC = member.Descendants("要約")FirstOrDefault()の値;
                             DESC = desc.Trim();
                             , desc.Split( new char [] { ' ' , 't' , 'n' }, StringSplitOptions.RemoveEmptyEntries)); 。DESC = 文字列結合(""、desc.Split( 新しいchar [] {''、'T'、'N'}、StringSplitOptions.RemoveEmptyEntries));

                             場合 (isType)
                             {
                                 builder.AddCallback(T、B => b.AddCustomAttributes( 新しいのDescriptionAttribute(降順)));
                             }
                             
                             {
                                 文字列 propNameプロパティ= name.Substring(lastDot + 1);
                                のPropertyInfoπ= t.GetProperty(propNameプロパティ);
                                 MethodInfoのマイル;
                                 && (mi = pi.GetSetMethod()) != null && mi.IsPublic) 場合 (π!= NULL&&(マイル= pi.GetSetMethod())!= NULL&&mi.IsPublic)
                                 {
                                     builder.AddCallback(T、B => b.AddCustomAttributes(propNameプロパティ、 新しいのDescriptionAttribute(降順)));
                                 }
                             }
                         }
                     }
                 }
                 キャッチ (例外電子)
                 {
                     .Format(CultureInfo.InvariantCulture, "Exception in AddDescriptions method: {0}" , e)); Debug.Assertの( 偽の文字列フォーマット(CultureInfo.InvariantCulture、"AddDescriptionsメソッドで例外:{0}"。、E));
                 }
             }
         }

         / / / <summary>
         / / / AttributeTableBuilderのサブクラスを作成せずにカスタム属性を追加する場所を提供する。
         / / / </概要>
         / / / <param name="builder">アセンブリの属性テーブルビルダ。</ PARAM>
         保護された仮想ボイド AddAttributes(AttributeTableBuilderビルダー)
         {
         }
     }
 } 

MetadataBase.csはMetadataRegistrationBaseクラスを実装します。 いくつかの主要なメソッドを説明しましょう​​:

AddDescriptions

すべての実行時のアセンブリのプロジェクトは、プロジェクトで、チェック"XMLドキュメントファイル"オプションを持っている、と".. BinariesMicrosoft.Windows.Controls.XML"のようなパスを持つ - >プロパティ - >ビルド]タブ、出力セクション。 。また、以下のようなcsprojファイルに設定を見つけることができます。

  > ..BinariesMicrosoft.Windows.Controls.Design.XML </ DocumentationFile > <DocumentationFile> .. BinariesMicrosoft.Windows.Controls.Design.XML </ DocumentationFile> 

以下の生成されたドキュメントのXMLファイルがどのようなものかを示すためにMicrosoft.Windows.Controls.XMLの抜粋は以下のとおりです。

  version ="1.0" ? > <?XML バージョン ="1.0"?>
 > < ドキュメント >
     > < アセンブリ >
         > Microsoft.Windows.Controls </ name > < 名前 > Microsoft.Windows.Controls </ 名前 >
     > </ アセンブリ >
     > < メンバー >
         name ="T:Microsoft.Windows.Controls.Viewbox" > < メンバー  ="T:Microsoft.Windows.Controls.Viewbox">
             > < 概要 >
            ストレッチとする単一の子を拡張できるコンテンツデコレータを定義します。
            利用可能なスペースを埋める。
             > </ 要約 >
             > Preview </ QualityBand > <QualityBand>プレビュー</ QualityBand>
         > </ メンバー >
         name ="F:Microsoft.Windows.Controls.Viewbox.ChildElementName" > < メンバー  ="F:Microsoft.Windows.Controls.Viewbox.ChildElementName">
             > < 概要 >
             Viewboxののデフォルトのテンプレートで子要素の名前。
             > </ 要約 >
         > </ メンバー >
         name ="M:Microsoft.Windows.Controls.Viewbox.IsValidStretchValue(System.Object)" > < メンバー  ="M:Microsoft.Windows.Controls.Viewbox.IsValidStretchValue(System.Objectの)">
             > < 概要 >
            オブジェクトの値で渡されるかどうか確認して有効なストレッチ列挙型値です。
             > </ 要約 >
             name ="o" > The object typed value to be checked. </ param > < パラメータ  ="O">オブジェクト型指定された値をチェックする。</ PARAM>
             > True if o is a valid Stretch enum value, false o/w. </ returns > < リターン > oが有効なストレッチ列挙値、偽のO / Wです。Trueの場合、</ リターン >
         > </ メンバー >
         name ="P:Microsoft.Windows.Controls.Viewbox.Child" > < メンバー  ="P:Microsoft.Windows.Controls.Viewbox.Child">
             > < 概要 >
             Viewboxのの単一の子要素を取得または設定します。
             > </ 要約 >
         > </ メンバー >
     > </ メンバー >
 > </ DOC> 

各の<member>要素のname属性は、パターンに従います。

  • "T:Microsoft.Windows.Controls.Viewbox":"Tは:"これはタイプの完全な名前が続くタイプ、であることを示します。
  • "F:Microsoft.Windows.Controls.Viewbox.ChildElementName":"F:"フィールドの完全修飾名に続いて、これがフィールドであることを示します。
  • "M:Microsoft.Windows.Controls.Viewbox.IsValidStretchValue(System.Objectの)":"M:"これは、メソッドの完全修飾名とパラメーターが続く方法、であることを示します。
  • "P:Microsoft.Windows.Controls.Viewbox.Child":"Pは:"これはプロパティの完全な名前が続く財産、であることを示します。

埋め込みリソースとしてMicrosoft.Windows.Controls.XMLファイルへControl.Designプロジェクトのリンク:

  • 埋め込みリソースとしてMicrosoft.Windows.Controls.XML
  • Controls.Design.csproj:

      Include ="..BinariesMicrosoft.Windows.Controls.XML" /> <EmbeddedResource 含める =".. BinariesMicrosoft.Windows.Controls.XML"/> 

AddDescriptionsメソッドは埋め込まれたXMLファイルを解析し、公共のコントロールクラスおよびそのパブリックプロパティのDescriptionAttributeとを生成します。

  MetadataBase.cs:134:builder.AddCallback(T、B => b.AddCustomAttributes( 新しいのDescriptionAttribute(降順)));
 MetadataBase.cs:143:builder.AddCallback(T、B => b.AddCustomAttributes(propNameプロパティ、 新しいのDescriptionAttribute(降順))); 
AddAttributes

AddAttributesは、​​設計者のツールボックスに表示されないはずのコントロールクラスのためにToolboxBrowsableAttribute(偽)カスタム属性を追加するには、通常Metadata.csファイルで上書きされます。

  • コントロールクラスは、すべての設計者から非表示にするかどうか、Xxx.Designのプロジェクトに(偽)カスタム属性をToolboxBrowsableAttributeを追加します。
  • それは、Visual Studioから隠される場合にのみ、プロジェクトをXxx.VisualStudio.Designにカスタム属性を追加します。
  • それが唯一のExpression Blendから非表示にするかどうか、プロジェクトをXxx.Expression.Designにカスタム属性を追加します。

以下Controls.VisualStudio.DesignプロジェクトのMetadata.csでAddAttributesの実装は、次のとおりです。

  / / / <summary>
 / / / AttributeTableBuilderのサブクラスを作成せずにカスタム属性を追加する場所を提供する。
 / / / </概要>
 / / / <param name="builder">アセンブリの属性テーブルビルダ。</ PARAM>
 保護されたオーバーライドボイド AddAttributes(AttributeTableBuilderビルダー)
 {
     ToolboxBrowsableAttribute( false ))); builder.AddCallback(typeof演算 (のTreeViewItem)、B => b.AddCustomAttributes( 新しい ToolboxBrowsableAttribute(  )));
 } 
AddTables

タイプのToolboxBrowsableAttribute(偽)以外の属性を追加するには、適切な設計プロジェクトに以下のViewboxMetadata.csのようなXxxMetadata.csファイルを追加します。

ViewboxMetadata.cs:

  / /(C)著作権Microsoft Corporationの。
 / /このソースMicrosoftパブリックライセンス(Ms - PL)の対象となります。
 / /詳細については、http://go.microsoft.com/fwlink/?LinkID=131993を参照してください。
 / /他のすべての権利を保有。

 System.ComponentModelを使用して、
 Microsoft.Windows.Controls.Design.Commonを使用して、
 Microsoft.Windows.Design.Metadataを使用して、

 名前空間 Microsoft.Windows.Controls.Design
 {
     / / / <summary>
     Viewboxのための設計時のメタデータを登録するには/ / /。
     / / / </概要>
     内部クラス ViewboxMetadata:AttributeTableBuilder
     {
         / / / <summary>
         Viewboxのための設計時のメタデータを登録するには/ / /。
         / / / </概要>
         公共 ViewboxMetadata()
            ベース ()
         {
            にaddCallback(
                 typeof演算 (Viewboxの)、
                 B =>
                 {
                     )); b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.BorderThickness)、 新しい BrowsableAttribute(  ));
                     )); b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.BorderBrush)、 新しい BrowsableAttribute(  ));
                     )); b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.Background)、 新しい BrowsableAttribute(  ));
                     )); b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.Foreground)、 新しい BrowsableAttribute(  ));

                     b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.Child)、 新しい CategoryAttribute(Properties.Resources.CommonProperties));
                     b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.Stretch)、 新しい CategoryAttribute(Properties.Resources.CommonProperties));
                     b.AddCustomAttributes(Extensions.GetMemberName <Viewbox>(X => x.StretchDirection)、 新しい CategoryAttribute(Properties.Resources.CommonProperties));
                 });
         }
     }
 } 
  • それはここに命名規則に従うことをお勧めします。 たとえば、Viewboxを取る、ファイル名はViewboxMetadata.csであり、クラス名はViewboxMetadataです。
  • メタデータクラスは、AttributeTableBuilderから継承する必要があります。
  • あなたは、メタデータクラスのコンストラクタでカスタム属性を追加することができます。
    • あなたはどちらのコールバックモデル(上記ViewboxMetada.csのように)またはダイレクトモデルを使用することができます。 コー​​ルバックモデルでは、おそらく、より効率的です。
      • ダイレクトモデルの例:

        AddCustomAttributes(

        typeof演算(Viewboxの)、/ /タイプ

        "borderThicknessの"、/ /プロパティ名

        新しい属性[] {新しいBrowsableAttribute(偽)}); / /カスタム属性の配列

    • AddCustomAttributeコールするプロパティの名前のパラメータを提供するには、どちらのタイプセーフな方法でプロパティ名を取得、または提供する(記事の後半で、それについて詳しく説明します)ViewboxMetadata.csのようにメソッドExtensions.GetMemberName()を使用することができます直接上記のダイレクトモデルの実装の"borderThicknessの"のような文字列としてプロパティ名。

AddTables(AttributeTableBuilderビルダー)方法:

  • 実行中のアセンブリにAttributeTableBuilderのすべてのサブクラスを列挙
  • 見つかった各AttributeTableBuilderのサブクラスのインスタンスを作成します。

    AttributeTableBuilder ATB =(AttributeTableBuilder)Activator.CreateInstanceを(T);

  • ビルダーに見つかったクラスの属性テーブルを追加します。

    builder.AddTable(atb.CreateTable());

Metadata.cs

Metadata.csはMetadataBase.csで実装MetadataRegistrationBaseクラスから継承MetadataRegistrationクラスを、実装しています。 また、実装してIRegisterMetadataインターフェイスを。

Metadata.cs:

 / /(C)著作権Microsoft Corporationの。/ /このソースは、Microsoftパブリックライセンス(Ms - PL)の対象となる。/ /詳細については、http://go.microsoft.com/fwlink/?LinkID=131993を参照してください。/ /他のすべての権利  MetadataRegistration : MetadataRegistrationBase, IRegisterMetadata { /// <summary> /// Design time metadata registration class. /// </summary> public MetadataRegistration() : base () { AssemblyName asmName = typeof (Viewbox).Assembly.GetName(); XmlResourceName = asmName.Name + ".Design." + asmName.Name + ".XML" ; // "Microsoft.Windows.Controls.Design.Microsoft.Windows.Controls.XML" AssemblyFullName = ", " + asmName.FullName; } /// <summary> /// Borrowed from System.Windows.Controls.Toolbox.Design.MetadataRegistration: /// use a static flag to ensure metadata is registered only one. /// </summary> private static bool _initialized; /// <summary> /// Called by tools to register design time metadata. /// </summary> public void Register() { if (!_initialized) { MetadataStore.AddAttributeTable(BuildAttributeTable()); _initialized = true ; } } /// <summary> /// Provide a place to add custom attributes without creating a AttributeTableBuilder subclass. /// </summary> /// <param name="builder">The assembly attribute table builder.</param> protected override void AddAttributes(AttributeTableBuilder builder) { } } } {/ / / <summary> / / / MetadataRegistrationクラス/ / / </概要> パブリッククラス MetadataRegistration:。。MetadataRegistrationBase、IRegisterMetadata {/ / / <summary> / / /デザイン時メタデータの登録クラス/ / / </概要> 公共 MetadataRegistration():。 基底 (){のAssemblyName asmName = typeof演算 (Viewboxの)Assembly.GetName(); XmlResourceName = asmName.Name +"。設計。"+ asmName.Name +"XML"、/ /"Microsoft.Windows 。Controls.Design.Microsoft.Windows.Controls.XML"AssemblyFullName ="、"+ asmName.FullName;} / / / <summary> / / / System.Windows.Controls.Toolbox.Design.MetadataRegistrationから借用:/ / / / / / <summary> / / /設計時のメタデータを登録するためのツールによって呼び出されます/ / /が</要約> 公共 ;。。</概要> プライベート静的なブール値は _initialized だけ/ / /を登録されているメタデータを確実にするために静的なフラグを使用して ()レジスタが無効になる {{MetadataStore.AddAttributeTable(()BuildAttributeTable) 場合 (_initialized!); _initialized = trueは ;}} / / / <summary> / / / AttributeTableBuilderのサブクラスを作成せずにカスタム属性を追加する場所を提供する/ /。 / </概要> / / / <param name="builder">アセンブリの属性テーブルビルダ。</ PARAM> 保護されたオーバーライドするvoid AddAttributes(AttributeTableBuilderビルダー){}}} 

その主要なメソッドのいくつかを説明しましょう​​:

MetadataRegistration

このコンストラクタは、2つのキーフィールドを初期化します。

  • XmlResourceName:MetadataRegistrationBase.AddDescriptionsメソッドで使用される埋め込みドキュメントのXMLファイルのリソース名、。
  • AssemblyFullName:実行時のアセンブリの完全名は、このデザイン時のアセンブリにするためです。

あなたがあなた自身の設計プロジェクトでMetadata.csを使用すれば、独自のクラスと型Viewboxを交換する必要があります。

登録

これが唯一の方法ですIRegisterMetadataのインタフェース。 それはAddDescripions、AddAttributes&AddTables方法は設計者のメタデータストアに、上記のように構築されたカスタム属性テーブルを、追加します。

MetadataStore.AddAttributeTable(BuildAttributeTable());

Extensions.cs

このファイルは、コンパイル時のチェックやIntelliSenseとタイプのメンバの名前を取得するために使用される拡張方法GetMemberName <T>(式<のFunc <T, object>は> exprの)の実装が含まれています。

GetMemberNameの拡張メソッド

アイデアは元々によって提案されたジャファルフサイン (彼のブログポストを参照してくださいC#3.0でシンボルを )し、改善しジャスティンエンジェル それはタイプミスを避けるために、偉大なトリックですが、欠点は、それ以外は純粋な。NETアセンブリにSilverlightの参照とアセンブリを取り込むことです。 ここで完全なソースは、次のとおりです。

Extensions.cs:

  / /(C)著作権Microsoft Corporationの。
 / /このソースMicrosoftパブリックライセンス(Ms - PL)の対象となります。
 / /詳細については、http://go.microsoft.com/fwlink/?LinkID=131993を参照してください。
 / /他のすべての権利を保有。

システムを使用して;
 System.Linq.Expressionsを使用して、

 名前空間 Microsoft.Windows.Controls.Design.Common
 {
     / / / <summary>
     / / /内部の拡張メソッドのセットは、一般的なソリューションを提供し、
     小さ ​​い十分な数の/ / /ユーティリティ専用の拡張を保証しないように
     クラス/ / /メソッド。
     / / / </概要>
     内部の静的クラスExtensions
     {
         / / / <summary>
         タイプミスを避けるために、コンパイル時の検証でメンバー名を取得する/ / /ヘルパーメソッド。
         / / / </概要>
         / / / <typeparam name="T">名のメンバーを含んでいるクラスが取得される。</ typeparam>
         / / / <param name="expr">通常Oの形でラムダ式を=> o.member。</ PARAM>
         / / / <returns>プロパティの名前。</リターン>
         >> expr) 公共の静的な文字列 GetMemberName <T>(式<のFunc <T, オブジェクト >> exprは)
         {
            式本体=((LambdaExpression)式)ボディ。
             MemberExpression として MemberExpressionのmemberExpression =体を;
             ) (memberExpression == nullの場合
             {
                 memberExpression =(MemberExpression)((UnaryExpression)ボディ)オペランド。。
             }
             memberExpression.Member.Nameを返します
         }
     }
 } 

結論

この記事は、に、設計時の機能の実装を説明2008年12月リリースSilverlightツールキット 、およびSilverlightコントロールのデザイン時の機能を実装するためのシンプルなフレームワークを導入しました。 あなたが実装をモデル化し、独自のプロジェクトでフレームワークを再利用することができます。 フレームワークは、それはすべてのブレンド今のサポートなので、メタデータのみの登録をサポートしている、まだ非常に原始的です。 私は、カスタムインライン/拡張/ダイアログエディタ、設計時のデータ、設計時にのみ動作等の追加など、Silverlightツールキットのためのフレームワークと設計時の機能の改善になります

私は前のポストに記載されているようにSilverlightツールキットの設計時の機能 、コントロールのデザイン時の経験は非常に重要です。 より多くのアプリケーションは、ユーザーがコントロールをドラッグアンドドロップしてレイアウトの変更など、ユーザーインターフェイスのカスタマイズの柔軟性を与えるので、それは、賜るの時間の機能とそれらのコントロールを使用する開発者の経験と生産性を向上させるだけでなく、エンドユーザーのエクスペリエンスを改善するだけでなく、またはそれが実行時であることを除いて、単にデザイナーのように、コントロールの設定を変更する。

  1. 08:19 2009年4月21日| #1

    @ Fider
    デバッグの場合、これを試してみてください。
    コントロールのアセンブリは、Cでfoo.dllの場合は*、、すなわち、制御、設計アセンブリの名前と位置が正しいか確認してください:\ tmpに、そしてデザインのアセンブリが​​cでfoo.design.dllです:\ tmpまたはC: \ TMP \デザイン。
    *、デザインのプロジェクトを開いて、登録関数にブレークポイントを設定し、Visual Studioを起動するためのデザインプロジェクトのプロパティのデバッグターゲットを設定する
    *ヒットF5、新しいVSのインスタンスが起動され、、、アイテムの選択]ダイアログを選択]を選択Silverlightのタブを通過し、新しいSLのプロジェクトを作成し、フォルダCに移動:\ tmpと、コントロールのdll foo.dllを選択します。
    *あなたのブレークポイントがヒットしてください。

    問題の別の一般的な原因:それはあなたがのためにメタデータを指定しているシルバーのタイプ(あなたの例でTreeViewItemAdv)であることを確認してください。

    この情報がお役に立てば幸い!

    おかげで、

    - 寧

  2. Fider
    3時18分時2009年4月21日| #2

    こんにちは寧、

    私は、アセンブリとして作成し、ローカルフォルダとGACに配置されている。 Silverlightの[コンポーネント]タブ - 私は選択項目]ダイアログボックスで、ローカルフォルダからアセンブリを開くしようとしています。 そのは、アセンブリ内のすべてのクラスを選択し、ツールボックスに追加されます。

    そう私に教えてどのように私はこれらのプロジェクトをデバッグするのですか

    よろしく、
    Fider

  3. Fider
    午前4時04分で2009年4月20日| #3

    こんにちは寧、

    良い記事。 私は私のSilverlightのカスタムコントロールのデザインとvisualstudio.designのプロジェクトが作成されました。 私の目的は、ツールボックスからクラスを非表示にすることだけです。 私は私でhiddedされるクラスにfalseにToolboxBrowsableAttributeを設定しているmetadata.csファイルを持っている。 私のmetadata.csファイルは次のようになります。

    パブリッククラスのメタデータ:IRegisterMetadata
    {

    公共ボイドレジスタ()
    {
    AttributeTableBuilderビルダーは=新しいAttributeTableBuilder();
    builder.AddCallback(typeof演算(TreeViewItemAdv)、B => b.AddCustomAttributes(新しいToolboxBrowsableAttribute(偽)));
    MetadataStore.AddAttributeTable(builder.CreateTable());
    }
    }

    私はまだクラスが表示されて得ることができる。

    すべてのヘルプは、かなりの量になるからです。

    よろしく、

    Fider。

    • 14:52 2009年4月20日| #4

      こんにちはFider、

      あなたのコードが右側に見えます。 私の提案は、あなたのコードが読み込まれ正常に実行されるかどうかを確認するためにステップスルーすることです。
      *あなたのRegister関数にブレークポイントを設定し、それがヒットされているかどうかを参照してください。 VS2010&Blend3使用新しいMWDと別のエントリポイント(代わりにIRegisterMetadata.RegisterのIProvideAttributeTable.AttributeTable)、およびデザインのDLLの名前や場所が、対応するランタイムDLLへの右の相対的ではない場合、デザインのdllができなくなりますどちらにロード。 これが問題の一般的な原因です。
      *ブレークポイントがヒットされている場合は、コードのステップ実行は、次にAttributeTable.ValidateTable、AttributeTable.GetCustomAttributes、またはTypeDescriptor.GetAttributesなどを経由して、効果を確認してください

      この情報がお役に立てば幸いです。

      おかげで、

      - 寧

  1. 18:31 2009年1月21日| #1
  2. 20時24分時2009年1月24日| #2
  3. 02:16 2009年3月31日| #3
  4. 11:48 2009年4月3日| #4
  5. 23:17 2009年4月22日| #5
  6. 13:14 2009年5月11日| #6