Архив

Архив за декабря 2008 года

Время разработки функций реализации в Silverlight Toolkit

28 декабря 2008 4 комментария

Введение

Это второй после моего Silverlight дизайн серии функций времени. Первый пост время разработки возможности в Silverlight Toolkit показал время разработки особенностей Silverlight Toolkit управления. Это сообщение объясняет, как она реализуется. Надеюсь, это сообщение может помочь объяснить наш исходный код, демонстрирующий, как реализовать функции проектирования для Silverlight, а также предоставление читателям основы и исходный код можно использовать непосредственно в их собственных проектах.

Обзор

Скачать "Silverlight Toolkit - Binaries, примеры, документация, модульные тесты и источники" в декабре 2008 выпуска , открытый SourceSilverlight.Controls.sln в Visual Studio, и мы увидим, что есть 12 дизайн-проектов под Дизайнерское решение папку, три для каждого элемента управления сборки.

Silverlight.Controls.sln в Visual Studio

Возьмите управления проектом, например, есть три дизайн-проекты:

  • Controls.Design: Windows.Controls.Design.dll сборки, которая содержит время разработки есть общим для обоих Visual Studio и Expression Blend.
  • Controls.Expression.Design: Windows.Controls.Expression.Design.dll сборки, которая содержит конструктивные особенности времени для Expression Blend только.
  • Controls.VisualStudio.Design: Windows.Controls.VisualStudio.Design.dll сборки, которая содержит конструктивные особенности времени для Visual Studio только.

Существует также Design.Common папку, которая содержит два файла: Extensions.cs и MetadataBase.cs, которые являются общими для всех дизайн-проектов.

Настоятельно рекомендуется прочитать блог Джастин Ангел сообщение Silverlight время разработки расширения : она обеспечивает хороший фон / общие сведения о Silverlight проектирования расширения, на которой ниже реализация основана.

Проект

Все 12 дизайн-проектов следовать той же схеме реализации, поэтому я буду просто использовать Control.Design проект объяснить их всех.

Загрузка Silverlight.Controls.sln в исходный каталог в Visual Studio в первый раз, мы увидим экран, как показано ниже:

Silverlight.Controls.Design.csproj в Visual Studio

  • Controls.Design есть проект зависимости от проекта управления. Эта зависимость гарантирует, что Управление проектом построен первый и Controls.Design имеет ссылку на Microsoft.Windows.Controls сборка построена по проекту управления. Сборка время разработки всегда ссылается на сборку во время выполнения обеспечивает конструктивные особенности времени.
  • Controls.Design ссылки Microsoft.Windows.Design и Microsoft.Windows.Design.Extensibility сборок, оба из которых находятся в каталоге% DevEnvDir% PublicAssemblies (C: Program FilesMicrosoft Visual Studio 9.0Common7IDEPublicAssemblies на моем ноутбуке). Сборка время разработки часто ссылается этих двух узлов, которые обеспечивают основу расширяемости конструктора. Сборка время разработки всегда ссылается система сборки тоже, который содержит имен System.ComponentModel, где многие из атрибутов метаданных (например, CategoryAttribute, DescriptionAttribute) определены.
  • Controls.Design ссылки System.Windows сборки. Мы видим, что ссылка в Controls.Design.csproj также:

    <reference Include="System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
    <SpecificVersion> False </ SpecificVersion>
    <HintPath> .. BinariesSystem.Windows.dll </ HintPath>
    <Private> False </ Private>
    </ Ссылка>

    Пожалуйста, обратите внимание:

    • Control.Design это библиотека для Windows класс проекта, а не проект Silverlight, а также созданные Microsoft.Windows.Controls.Design.dll является NET сборки работают на рабочий стол в дизайнеров, таких как Visual Studio и Expression Blend, а не сборки Silverlight выполняются внутри. браузер, хотя Microsoft.Windows.Controls.Design.dll это собрание время разработки на данный момент Silverlight Microsoft.Windows.Controls.dll сборки перспективе.
    • Ссылка System.Windows сборки на самом деле является Silverlight сборки (версия 2.0.5.0). System.Windows сборки не может быть необходима для всех дизайн-проектов для элементов управления Silverlight. Мы должны здесь в основном из-за GetMemberName <T> (Expression <Func <T, object>> выражение) метода в Extension.cs, что мы будем обсуждать позже в этой должности. Смесь. NET и Silverlight ссылки создаются всевозможные интересные вопросы, как мы увидим в ближайшее время.

      Ниже ILDASM скриншот показывает смешанные ссылки на NET и Silverlight сборки, Microsoft.Windows.Controls.Design.dll.:
      ILDASM Microsoft.Windows.Controls.Design.dll Microsoft.Windows.Controls.Design манифеста сборки

      • . Версии 2:0:21024:1838 это номер версии Silverlight Toolkit выпуска декабрь 2008.
      • . Версии 3:5:0:0 это номер версии. NET Framework 3.5.
      • . Версии 2:0:0:0 это номер версии Silverlight 2.0.
    • Когда вы первый проект Controls.Design нагрузки в Visual Studio, есть "" System.Windows "ссылается компонент не может быть найден" предупреждение рядом с ссылкой System.Windows сборки в окне проекта, и в окне Список ошибок тоже. Это потому, что это Controls.Design NET проект вместо Silverlight, и мы не знаем, где Silverlight установлен (он находится в C:. Программа FilesMicrosoft Silverlight2.0.31005.0 на моем ноутбуке, и в C: Program Files (X86 ) Microsoft Silverlight2.0.31005.0 на моем рабочем столе). Решение состоит в том, чтобы событие перед построением команд .. CopySystemWindows.bat, которая копирует System.Windows.dll от направления Silverlight для установки .. Binaries. Поэтому, как только вы создали проект, предупреждение исчезнет, ​​как мы увидим в ближайшее время.
  • В вышеприведенном скриншоте визуальные студии, есть еще один предупредительный знак рядом с файлом Microsoft.Windows.Controls.XML в проекте вдовы, когда вы загружаете Controls.Design проекта в Visual Studio в первый раз. Этот файл создается путем создания зависимых проектов управления, потому что в свойствах управления проекта -> Build вкладке опцию "XML-файл документации" проверяется, и имеет путь "Бинар ..
    iesMicrosoft.Windows.Controls.XML ". Если вы строите Controls.Design проекта, предупреждение исчезнет, ​​как мы увидим в ближайшее время.
  • Controls.Design проект Metadata.cs файла и ссылки на Extension.cs и MetadataBase.cs в Design.Common папку. Все 12 проектов, дизайн у этих трех файлов. Мы обсудим их более подробно.

Сборка проекта Controls.Design или всего решения, мы можем видеть:

Построить выход Silverlight.Control.sln

  • Все проекты, построенные в порядке с 0 ошибок и 0 предупреждений.
  • Предупредительных знаков рядом с System.Windows ведения и Microsoft.Windows.Controls.XML файл исчез.
  • Код анализ процесса сборки занимает много времени, и она генерирует два предупреждения. Первый из них, CA0060, еще один вопрос, смешанных. NET и Silverlight ссылки и код Extension.cs. Вы можете избавиться от предупреждения, копируя System.dll и System.Core.dll из каталога установки Silverlight в каталог SourceBinaries и строительство заново.

MetadataBase.cs

MetadataBase.cs вместе с Metadata.cs, ​​осуществлять основу для разработки регистрации метаданных времени:

  • DescriptionAttributes автоматически генерируются для общественных классов управления (например, подклассов FrameworkElement) и их общие свойства с их "/ / / <summary>" XML комментарии документации в исходном коде. (Хорошо комментируя платит! :-) )
  • Чтобы скрыть контроль класс от дизайнера, добавьте строку ниже AddAttributes метод Metadata.cs файле проекта:
    builder.AddCallback (TypeOf (TreeViewItem), б => b.AddCustomAttributes (новая ToolboxBrowsableAttribute (ложь)));
  • Для регистрации других пользовательских атрибутов для класса элемента управления, добавьте XxxMetadata.cs файл в проект, как ViewboxMetadata.cs обсуждаться позже.

Если вы любите рамках, вы можете использовать MetadataBase.cs и Metadata.cs прямо в свой ​​собственный проект, с учетом Microsoft Public License включена в начале всех наших исходных файлов.

MetadataBase.cs:

 / / (С) Copyright Microsoft Corporation. / / Этот источник зависит от лицензии Microsoft Public (Ms-PL). / / См. http://go.microsoft.com/fwlink/?LinkID=131993 подробнее /. / Все другие права,  MetadataRegistrationBase { /// <summary> /// Build design time metadata attribute table. /// </summary> /// <returns>Custom attribute table.</returns> protected virtual AttributeTable BuildAttributeTable() { AttributeTableBuilder builder = new AttributeTableBuilder(); AddDescriptions(builder); AddAttributes(builder); AddTables(builder); return builder.CreateTable(); } /// <summary> /// Find all AttributeTableBuilder subclasses in the assembly /// and add their attributes to the assembly attribute table. /// </summary> /// <param name="builder">The assembly attribute table builder.</param> [SuppressMessage( "Microsoft.Design" , "CA1031:DoNotCatchGeneralExceptionTypes" , Justification = "Design time dll should not fail!" )] private static void AddTables(AttributeTableBuilder builder) { Debug.Assert(builder != null , "AddTables is called with null parameter!" ); Assembly asm = Assembly.GetExecutingAssembly(); foreach (Type t in asm.GetTypes()) { if (t.IsSubclassOf( typeof (AttributeTableBuilder))) { try { AttributeTableBuilder atb = (AttributeTableBuilder)Activator.CreateInstance(t); builder.AddTable(atb.CreateTable()); } catch (Exception e) { Debug.Assert( false , string .Format(CultureInfo.InvariantCulture, "Exception in AddTables method: {0}" , e)); } } } } /// <summary> /// Gets or sets the case sensitive resource name of the embedded XML file. /// </summary> protected string XmlResourceName { get; set; } /// <summary> /// Gets or sets the assembly FullName for types' assembly-qualified names. /// </summary> protected string AssemblyFullName { get; set; } /// <summary> /// Create description attribute from run time assembly xml file. /// </summary> /// <param name="builder">The assembly attribute table builder.</param> [SuppressMessage( "Microsoft.Design" , "CA1031:DoNotCatchGeneralExceptionTypes" , Justification = "Design time dll should not fail." )] private void AddDescriptions(AttributeTableBuilder builder) { Debug.Assert(builder != null , "AddDescriptions is called with null parameter!" ); if ( string .IsNullOrEmpty(XmlResourceName) || string .IsNullOrEmpty(AssemblyFullName)) { return ; } XDocument xdoc = XDocument.Load( new StreamReader( Assembly.GetExecutingAssembly().GetManifestResourceStream(XmlResourceName))); if (xdoc == null ) { return ; } foreach (XElement member in xdoc.Descendants( "member" )) { try { string name = ( string )member.Attribute( "name" ); bool isType = name.StartsWith( "T:" , StringComparison.OrdinalIgnoreCase); if (isType || name.StartsWith( "P:" , StringComparison.OrdinalIgnoreCase)) { int lastDot = name.Length; string typeName; if (isType) { typeName = name.Substring(2); } else { lastDot = name.LastIndexOf( '.' ); typeName = name.Substring(2, lastDot - 2); } typeName += AssemblyFullName; Type t = Type.GetType(typeName); if (t != null && t.IsPublic && t.IsClass && t.IsSubclassOf( typeof (FrameworkElement))) { string desc = member.Descendants( "summary" ).FirstOrDefault().Value; desc = desc.Trim(); desc = string .Join( " " , desc.Split( new char [] { ' ' , 't' , 'n' }, StringSplitOptions.RemoveEmptyEntries)); if (isType) { builder.AddCallback(t, b => b.AddCustomAttributes( new DescriptionAttribute(desc))); } else { string propName = name.Substring(lastDot + 1); PropertyInfo pi = t.GetProperty(propName); MethodInfo mi; if (pi != null && (mi = pi.GetSetMethod()) != null && mi.IsPublic) { builder.AddCallback(t, b => b.AddCustomAttributes(propName, new DescriptionAttribute(desc))); } } } } } catch (Exception e) { Debug.Assert( false , string .Format(CultureInfo.InvariantCulture, "Exception in AddDescriptions method: {0}" , e)); } } } /// <summary> /// Provide a place to add custom attributes without creating a AttributeTableBuilder subclass. /// </summary> /// <param name="builder">The assembly attribute table builder.</param> protected virtual void AddAttributes(AttributeTableBuilder builder) { } } } {/ / / <summary> / / / MetadataRegistration класса. / / / </ Резюме> общественный класс MetadataRegistrationBase {/ / / <summary> / / / Build время разработки метаданные таблицы атрибутов. / / / </ Резюме> / / / <returns> пользовательских атрибутов таблицы </ возвращает> защищенных виртуальных AttributeTable BuildAttributeTable () {AttributeTableBuilder строитель = новый AttributeTableBuilder (); AddDescriptions (строитель); AddAttributes (строитель); AddTables (строитель); возвращение builder.CreateTable ();} /. / / <summary> / / / Найти все AttributeTableBuilder подклассов в сборке / / / и добавляем их атрибутов в таблице атрибутов сборки. / / / </ резюме> / / / <param name="builder"> таблице атрибут сборки строитель </ параметра>. [SuppressMessage ("Microsoft.Design", "CA1031: DoNotCatchGeneralExceptionTypes" Обоснование = "! DLL время разработки не должны потерпеть неудачу")] частных статических AddTables недействительными (AttributeTableBuilder строитель) {Debug.Assert (строитель =! нулевой "AddTables вызывается с нулевым параметром!"); Ассамблеи АНМ = Assembly.GetExecutingAssembly (); Еогеасп (типа т в asm.GetTypes ()) {если (t.IsSubclassOf (TypeOf (AttributeTableBuilder))) {try {AttributeTableBuilder ATB = (AttributeTableBuilder) Activator.CreateInstance (т); builder.AddTable (atb.CreateTable ());} catch (Exception е) {Debug.Assert (ложь, строка формата (CultureInfo.InvariantCulture "Исключение в методе AddTables. {0} ", е));}}}} / / / <summary> / / / Возвращает или задает регистр имя ресурса к файлу встроенный XML / / / </ резюме> охраняемой XmlResourceName строка {get;. установить ;} / / / <summary> / / / Возвращает или задает сборку FullName для сборки квалифицированными типов имен / / / </ резюме> охраняемой AssemblyFullName строка {get;. установлен;} / / / <summary> / / / Создать описание атрибута во время выполнения файла сборки XML / / / </ резюме> / / / <param name="builder"> таблице атрибут сборки строитель </ параметр> [SuppressMessage ("Microsoft.Design", "CA1031..: DoNotCatchGeneralExceptionTypes "Обоснование =" DLL время разработки не должны потерпеть неудачу ")] частные AddDescriptions недействительными (AttributeTableBuilder строитель) {Debug.Assert (строитель = NULL,"! AddDescriptions вызывается с нулевым параметром ").!. если (строка IsNullOrEmpty ( XmlResourceName) | | строки IsNullOrEmpty (AssemblyFullName)) {return;} XDocument xdoc = XDocument.Load (новый StreamReader (Assembly.GetExecutingAssembly ().. GetManifestResourceStream (XmlResourceName))), если (xdoc == NULL) {return;} Еогеасп (XElement член xdoc.Descendants ("член")) {try {строка имя = (строка) member.Attribute ("имя"); Ьоо isType = name.StartsWith ("T", StringComparison.OrdinalIgnoreCase), если ( 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, типа т = Type.GetType (TypeName), если (Т = NULL && t.IsPublic t.IsClass && && t.IsSubclassOf (TypeOf (FrameworkElement))) {строка по убыванию = member.Descendants ("резюме") FirstOrDefault () Значение,.. по убыванию desc.Trim = ();. по убыванию = строка регистрации ("", desc.Split ( новый символ [] {'', 'т', 'п'}, StringSplitOptions.RemoveEmptyEntries)), если (isType) {builder.AddCallback (T, B => b.AddCustomAttributes (новая DescriptionAttribute (по убыванию)));} еще {строка PROPNAME = name.Substring (lastDot + 1); PropertyInfo пи = t.GetProperty (PROPNAME); MethodInfo миль;!, если (р = NULL && (т = pi.GetSetMethod ()) = NULL && mi.IsPublic ) {builder.AddCallback (T, B => b.AddCustomAttributes (PROPNAME, новые DescriptionAttribute (по убыванию)));}}}}} catch (Exception е) {Debug.Assert (ложь, строка формата (CultureInfo.InvariantCulture. "Исключение в методе AddDescriptions: {0}"., е));}}} / / / <summary> / / / Предоставление места для добавления пользовательских атрибутов без создания AttributeTableBuilder подкласс / / / </ резюме> / / / <param name="builder"> таблице атрибут сборки строителя. </ параметра> защищенных виртуальных 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> 

Ниже приводится выдержка из Microsoft.Windows.Controls.XML чтобы показать, что созданные документы 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 (Иерархия)">
             > <Резюме>
             Проверьте, правильно ли прошли в объект значение является допустимым значением перечисления Stretch.
             > </ Резюме>
             name ="o" > The object typed value to be checked. </ param > <Имя параметра = "о"> объект типизированного значения должны быть проверены. </ Параметров>
             > True if o is a valid Stretch enum value, false o/w. </ returns > <Возвращения> Правда, если а является допустимым значением перечисления Stretch, ложные м / в. </ Возвращает>
         > </ Член>
         name ="P:Microsoft.Windows.Controls.Viewbox.Child" > <Имя пользователя = "P: Microsoft.Windows.Controls.Viewbox.Child">
             > <Резюме>
             Получает или задает один дочерний элемент Viewbox.
             > </ Резюме>
         > </ Член>
     > </ Члены>
 > </ DOC> 

Имя атрибута каждого <member> элемент соответствует шаблону:

  • "T: Microsoft.Windows.Controls.Viewbox": "T" указывает, что это тип, а затем полное имя типа;
  • "F: Microsoft.Windows.Controls.Viewbox.ChildElementName": "F:" указывает на это поле, а затем поля это полное имя;
  • "М: Microsoft.Windows.Controls.Viewbox.IsValidStretchValue (Иерархия)": "М" указывает, что это метод, а затем метод это полное имя и параметры;
  • "P: Microsoft.Windows.Controls.Viewbox.Child": "P" указывает, что это имущество, а затем полное имя свойства;

Control.Design проекте ссылки на Microsoft.Windows.Controls.XML файл как внедренный ресурс:

  • Microsoft.Windows.Controls.XML как внедренный ресурс
  • Controls.Design.csproj:

      Include ="..BinariesMicrosoft.Windows.Controls.XML" /> <EmbeddedResource Include = ".. 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, как правило, переопределения в Metadata.cs файл, чтобы добавить ToolboxBrowsableAttribute (ложь) пользовательских атрибутов для управления классами, которые не должны отображаться в панели инструментов дизайнера:

  • если класс элемента управления должны быть скрыты от всех дизайнеров, добавить ToolboxBrowsableAttribute (ложь) пользовательских атрибутов Xxx.Design проекта;
  • если оно должно быть скрыто от Visual Studio только добавить пользовательский атрибут в проекте Xxx.VisualStudio.Design;
  • если оно должно быть скрыто от Expression Blend только добавить пользовательский атрибут в проекте Xxx.Expression.Design;

Ниже AddAttributes реализации в Metadata.cs проекта Controls.VisualStudio.Design:

  / / / <summary>
 / / / Предоставление места для добавления пользовательских атрибутов без создания AttributeTableBuilder подкласса.
 / / / </ Резюме>
 / / / <param Name="builder"> таблице атрибут сборки строителя. </ Параметров>
 защита коррекции недействительным AddAttributes (AttributeTableBuilder строитель)
 {
     ToolboxBrowsableAttribute( false ))); builder.AddCallback (TypeOf (TreeViewItem), б => b.AddCustomAttributes (новая ToolboxBrowsableAttribute (ложь)));
 } 
AddTables

Чтобы добавить атрибуты, кроме ToolboxBrowsableAttribute (ложь) для типа, добавьте XxxMetadata.cs файл как ViewboxMetadata.cs ниже соответствующего проекта дизайна:

ViewboxMetadata.cs:

 / / (С) Copyright Microsoft Corporation. / / Этот источник зависит от лицензии Microsoft Public (Ms-PL). / / См. http://go.microsoft.com/fwlink/?LinkID=131993 подробнее /. / Все другие права,  ViewboxMetadata : AttributeTableBuilder { /// <summary> /// To register design time metadata for Viewbox. /// </summary> public ViewboxMetadata() : base () { AddCallback( typeof (Viewbox), b => { b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.BorderThickness), new BrowsableAttribute( false )); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.BorderBrush), new BrowsableAttribute( false )); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.Background), new BrowsableAttribute( false )); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.Foreground), new BrowsableAttribute( false )); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.Child), new CategoryAttribute(Properties.Resources.CommonProperties)); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.Stretch), new CategoryAttribute(Properties.Resources.CommonProperties)); b.AddCustomAttributes(Extensions.GetMemberName<Viewbox>(x => x.StretchDirection), new CategoryAttribute(Properties.Resources.CommonProperties)); }); } } } {/ / / <summary> / / / Чтобы зарегистрироваться время разработки метаданных для Viewbox / / / </ резюме> внутренний класс ViewboxMetadata.. AttributeTableBuilder {/ / / <summary> / / / Для регистрации метаданных времени разработки для Viewbox / / / </ резюме> общественный ViewboxMetadata (): базовый () {AddCallback (TypeOf (Viewbox), б => {b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.BorderThickness), новые BrowsableAttribute (ложь)) ; b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.BorderBrush), новые BrowsableAttribute (ложь)); b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.Background), новые BrowsableAttribute (ложь )); b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.Foreground), новые BrowsableAttribute (ложь)); b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.Child), новые CategoryAttribute (Properties.Resources.CommonProperties)); b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> (х => x.Stretch), новые CategoryAttribute (Properties.Resources.CommonProperties)); b.AddCustomAttributes (Extensions.GetMemberName <Viewbox> ( х => x.StretchDirection), новые CategoryAttribute (Properties.Resources.CommonProperties));});}}} 
  • Рекомендуется следовать именования здесь. Возьмите Viewbox например, имя файла ViewboxMetadata.cs, ​​и имя класса ViewboxMetadata.
  • Метаданных класс должен наследоваться от AttributeTableBuilder.
  • Вы можете добавлять пользовательские атрибуты в конструкторе класса метаданных:
    • Можно использовать как модель обратного вызова (как в ViewboxMetada.cs выше) или прямой модели. Модели обратного вызова, предположительно, более эффективным.
      • прямой пример модели:

        AddCustomAttributes (

        TypeOf (Viewbox), / / ​​тип

        "BorderThickness", / / ​​имя свойства

        новый атрибут [] {нового BrowsableAttribute (ложь)}); / / массив пользовательских атрибутов

    • Для обеспечения свойства параметра имя AddCustomAttribute звонок, вы можете использовать метод Extensions.GetMemberName (), как в ViewboxMetadata.cs (обсудим это позже на посту), чтобы получить имя свойства в типе безопасным способом, или предоставить имя свойства непосредственно в виде строки, как "BorderThickness" в выше прямой реализации модели.

AddTables (AttributeTableBuilder строитель) метода:

  • перечисляет все подклассы AttributeTableBuilder в выполнении сборки
  • создает экземпляр каждого найденного AttributeTableBuilder подкласса:

    AttributeTableBuilder ATB = (AttributeTableBuilder) Activator.CreateInstance (т);

  • добавить атрибут таблицы найден класс строитель:

    builder.AddTable (atb.CreateTable ());

Metadata.cs

Metadata.cs реализует MetadataRegistration класс, который наследует от класса MetadataRegistrationBase реализованы в MetadataBase.cs. Он также реализует IRegisterMetadata интерфейс.

Metadata.cs:

  / / (С) Copyright Microsoft Corporation.
 / / Этот источник зависит от лицензии Microsoft Public (Ms-PL).
 / / См. http://go.microsoft.com/fwlink/?LinkID=131993 подробности.
 / / Все остальные права защищены.

 using System.Reflection;
 использование Microsoft.Windows.Controls.Design.Common;
 использование Microsoft.Windows.Design.Metadata;

 Пространство имен Microsoft.Windows.Controls.Design
 {
     / / / <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:
         / / / Использовать статический флаг для обеспечения метаданных зарегистрирован только один.
         / / / </ Резюме>
         частных статических Ьоо _initialized;

         / / / <summary>
         / / / Вызывается инструменты для регистрации метаданных времени разработки.
         / / / </ Резюме>
         Регистрация общественных недействительными ()
         {
             если (! _initialized)
             {
                 MetadataStore.AddAttributeTable (BuildAttributeTable ());
                 _initialized = true;
             }
         }

         / / / <summary>
         / / / Предоставление места для добавления пользовательских атрибутов без создания AttributeTableBuilder подкласса.
         / / / </ Резюме>
         / / / <param Name="builder"> таблице атрибут сборки строителя. </ Параметров>
         защита коррекции недействительным AddAttributes (AttributeTableBuilder строитель)
         {
         }
     }
 } 

Давайте рассмотрим некоторые из ее основных методов:

MetadataRegistration

Этот конструктор инициализирует два ключевых областях:

  • XmlResourceName: имя ресурса, вложенного файла документации XML, используемый метод MetadataRegistrationBase.AddDescriptions.
  • AssemblyFullName: полное наименование перспективе время сборки данной сборке время разработки для.

Вам нужно заменить тип Viewbox своими класс, если вы используете Metadata.cs в ваш собственный дизайн проекта.

Регистрировать

Это единственный метод IRegisterMetadata интерфейс. Он добавляет пользовательские таблицы атрибутов, построенный из AddDescripions, AddAttributes и AddTables методов, описанных выше, в хранилище метаданных дизайнера:

MetadataStore.AddAttributeTable (BuildAttributeTable ());

Extensions.cs

Этот файл содержит реализацию метода расширения GetMemberName <T> (Expression <Func <T, object>> выражение), который используется для получения имени члена типа компиляции проверку временем и IntelliSense:

GetMemberName метод расширения

Эта идея была первоначально предложенный Джафар Хусейн (см. его сообщение в блоге символы в C # 3.0 ), а затем улучшить Джастин Ангел . Это большая уловка, чтобы избежать опечаток, но недостатком является то, что он тянет в ссылки Silverlight и сборки в противном случае чисто. NET сборки. Вот полный исходный код:

Extensions.cs:

  / / (С) Copyright Microsoft Corporation.
 / / Этот источник зависит от лицензии Microsoft Public (Ms-PL).
 / / См. http://go.microsoft.com/fwlink/?LinkID=131993 подробности.
 / / Все остальные права защищены.

 using System;
 использование System.Linq.Expressions;

 Пространство имен Microsoft.Windows.Controls.Design.Common
 {
     / / / <summary>
     / / / Этот набор внутренних методов расширения обеспечивает общие решения и
     / / / Коммунальные услуги в небольшом достаточное количество, чтобы не гарантирует расширение выделенного
     / / / Методы класса.
     / / / </ Резюме>
     Расширение внутреннего статического класса
     {
         / / / <summary>
         / / / Вспомогательный метод для получения имени члена компиляции проверку временем, чтобы избежать опечатки.
         / / / </ Резюме>
         / / / <typeparam Name="T"> содержащих класс члена, фамилия которого получен. </ Typeparam>
         / / / <param Name="expr"> лямбда-выражения, как правило, в виде о => o.member. </ Параметров>
         / / / <returns> Имя свойства. </ Возвращает>
         >> expr) общественности статической строки GetMemberName <T> (Expression <Func <T, объект>> выражение)
         {
             Выражение тело = ((LambdaExpression) выражение) тело.
             MemberExpression MemberExpression = тело MemberExpression;
             ) если (MemberExpression == NULL)
             {
                 MemberExpression = (MemberExpression) ((UnaryExpression) тела) операнда.
             }
             вернуться memberExpression.Member.Name;
         }
     }
 } 

Заключение

Это сообщение описывает реализацию конструктивных особенностей времени в декабре 2008 выпуск из Silverlight Toolkit и представила простой рамки для осуществления проектирования функций для элементов управления Silverlight. Вы можете моделировать реализации и использовать в рамках собственных проектов. Рамки все еще очень примитивно, поддерживающих метаданные только регистрация, так как это все Blend поддерживает на данный момент. Я буду смотреть в улучшении структуры и особенностей проектирования для Silverlight Toolkit, как добавление пользовательских встроенные / расширенные / диалог редакторов, данные проектирования, проектирования только поведения и т.д.

Как я уже говорил в предыдущем посте время разработки возможности в Silverlight Toolkit , время разработки опыта для управления очень важны. Это не только повышает производительность и опыт разработчиков, которые используют эти элементы управления с функциями, извольте, но также улучшает опыта конечных пользователей, поскольку все больше и больше приложений предоставляет пользователям большую гибкость в настройке пользовательского интерфейса, такие как изменение макета, перетаскивания элементов управления или изменения настроек управления, так же, как в конструкторе, кроме этого, во время выполнения.