Редактирование модели и по умолчанию Initializer для управления Silverlight
Введение
Это является частью серии по дизайну времени функция осуществления в Silverlight Инструментарий . Это сообщение используется инициализатор диаграммы по умолчанию, чтобы проиллюстрировать, как реализовать по умолчанию для инициализации Silverlight контроля, а также объяснить, лежащих в основе архитектуры модели редактирования.
Опыт
Если вы устанавливаете Silverlight 3 Инструментарий в марте 2009 выпуска , вы можете перетащить Диаграмма управления активами от Blend библиотека и поместите его на поверхность дизайнер, и у вас график красиво инициализируется и оказания услуг:
Вы можете узнать больше об этом в ходе ранее пост Silverlight Инструментарий Дизайн Время Особенности: март 2009 выпуска обновления .
Архитектура
DefaultInitializer
Это на самом деле довольно просто обеспечить по умолчанию для инициализации элемента управления Silverlight:
- осуществлять подкласс DefaultInitializer , и переопределить его InitializeDefaults функции
- ассоциированных инициализатор класса по умолчанию с контролем классе по FeatureAttribute
Ниже скриншот показывает осуществления DefaultInitializer абстрактный базовый класс, а другие классы в Microsoft.Windows.Design.Model имен, которые будут обсуждаться коротко:
Инициализация выполняется в InitializeDefaults преодолеть, и результат сериализуется в XAML. Так что первый шаг в реализации по умолчанию инициализатор является определение желаемого XAML, который будет производиться.
Редактирование модели
После того, результат определяется XAML, я хочу есть более высокий уровень абстракции / метод, который бы просто взять XAML. Но, к сожалению, мы должны использовать гораздо более низком уровне (таким образом, более гибкий и мощный) необходимо API называемая модель редактирования, который состоит из классов, как ModelItem , ModelProperty , ModelEvent , ModelFactory и ModelService . На странице MSDN Редактирование модели Архитектура дает обзор основных:
Ваша конструкция времени реализации взаимодействует с во время выполнения контроля, хотя программный интерфейс называется редактирования модели. Объекты, предназначенные называются редактируемых объектов.
Ваш контроля определяются в Extensible Markup Language применения (XAML). Вы обновить XAML для управления программным путем с помощью редактирования модели.
Модель, Wrapper и Открыть
Редактирования модели состоит из трех функциональных подразделений: модели общественного обертка, что тезисы модель, и считаем, что представляет собой пользовательский интерфейс (UI) модели. Модель и вид разных, но обертка и модели тесно связаны между собой. На следующем рисунке показано соотношение между тремя подразделениями.
Дизайн среды использует ModelItem типа для связи с базовой модели. Все изменения, внесенные в ModelItem оберток, которые влияют на основные модели. Это позволяет модели быть простой. ModelItem обертки обрабатывать сложные функции дизайнера, например, сопровождение сделок, отменить отслеживания и уведомления об изменениях.
Ниже диаграмма классов может помочь объяснить взаимосвязь между основными классами редактирования модели:
Использование XAML ниже в качестве примера:
<UserControl xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: х = "http://schemas.microsoft.com/winfx/2006/xaml" Width ="640" Height ="480" > х: класс = "ModelTest.Page" ширина = "640" высота = "480"> x:Name ="LayoutRoot" Background ="White" > <Grid х: Name = "LayoutRoot" Background = "Белое"> x:Name ="Button" > Кнопка <х: Name = "Кнопка"> x:Name ="Rectangle" /> <Прямоугольник х: Name = "Прямоугольник" /> > </ Кнопки> > </> Grid > </> UserControl
- ModelItem: предположим, переменная пункта ModelItem для управления кнопки выше,
- Название это сохраняется как х: Имя атрибута XAML: item.Name = "Button" является сохраняются в XAML, как х: Name = "Button".
- ItemType является тип объекта основных контроля, и постановляет, теги, используемые в XAML: item.PropertyType == tyepof (кнопка) и XAML тег <button />.
- Свойства Набор свойств, завернутый в типе ModelProperty, подстилающей контроля. Например: [пункт "ClickMode"] = ClickMode.Release будет упорно XAML, как ClickMode = "Release".
- Права представляет собой права собственности определены в ContentControl (и унаследовал его подклассы): item.Content является ModelItem представляющих объект прямоугольник.
- Источник: когда ModelItem представляет собой элемент, который в собственность другого элемента, источник ModelProperty обертка этого имущества. Например, item.Content.Value.Source item.Content == / / Прямоугольник.
- События представляет совокупность событий базового контроля, завернутый в ModelEvent типа. Из моего опыта отладки, это всегда нулевой, так кажется События собственности еще не поддерживается Blend3 для Silverlight3 еще.
- Родитель логики родителей базового контроля, завернутый в ModelItem типа. например: item.Parent является ModelItem для Grid.
- Корень ModelItem обертка для корневых визуальных, например: item.Root представляет UserControl.
- ModelProperty: предположим, переменная является опорой для ModelProperty Button.Content, т. е. свойства = item.Content,
- Имя это имя свойства базового контроля. Она сохраняется в XAML в качестве атрибута. например: prop.Name == "Содержимое".
- PropertyType является тип объекта имущества основных контроля этого объекта ModelProperty представляет. например: prop.PropertyType = ЪуреоЕ (объекта).
- AttachedOwnerType является тип объекта управления, что первая определяет собственности этого объекта ModelProperty представляет. например: prop.AttachedOwnerType == ЪуреоЕ (ContentControl) / / Примечание: не кнопки.
- Значение стоимости имущества базового контроля, завернутый в ModelItem типа. например: prop.Value является ModelItem представляющих объект прямоугольник.
- Родитель является контроль, завернутый в ModelItem типа, в том числе имущество принадлежит. например: prop.Parent == пункта.
- ModelEvent: как упоминалось выше, item.Events всегда нулевой, так что не кажется, что ModelEvent поддерживается в Blend3 для Silverlight3 еще. Но предположим, это работает, и переменной ЭВТ является ModelEvent для Button.Click, т. е. ЭВТ item.Events = ["Click"],
- Это имя события. например: evt.Name == "Click".
- EventType это тип делегата события, например: evt.EventType == ЪуреоЕ (RoutedEventHandler).
- Обработчики это строка коллекция обработчиков событий, например: evt.Handlers = новая строка [] ("Button_Click") будет упорно, как клик = "Button_Click". Примечание: это чистой воды спекуляция, поскольку ModelEvent пока не поддерживается, и я не знаю, / когда / как она будет поддерживаться на Silverlight.
- Родитель является контроль, завернутый в ModelItem типа, из которых это событие относится. например: evt.Parent == пункта.
Осуществление
По умолчанию диаграмма инициализатор класса ChartDefaultInitializer осуществляется в ChartDefaultInitializer.cs и зарегистрирован в ChartMetadata.cs. Оба файла находятся в Controls.DataVisualization.Toolkit.Design.csproj из Silverlight.Controls.Design.sln. Пожалуйста, прочитайте до должности Дизайн Время выполнения функций в Silverlight Инструментарий для получения дополнительной информации.
Результат XAML
В качестве первого шага, определить результат XAML быть изготовлен ChartDefaultInitializer:
Title ="Chart Title" > < Charting:Chart.DataContext > < PointCollection > < Point X ="1" Y ="10" /> < Point X ="2" Y ="20" /> < Point X ="3" Y ="30" /> < Point X ="4" Y ="40" /> </ PointCollection > < Charting:Chart.Series > < Charting:ColumnSeries ItemsSource ="{Binding}" DependentValuePath ="X" IndependentValuePath ="Y" /> </ Charting:Chart.Series > </ Charting:Chart.DataContext > </ Charting:Chart > <Диаграмм: Диаграмма Title = "Заголовок диаграммы"> <диаграмм: Chart.DataContext> <PointCollection> <точка X = "1" Y = "10" /> <точка X = "2" Y = "20" /> < Точка X = "3" Y = "30" /> <точка X = "4" Y = "40" /> </ PointCollection> <диаграмм: Chart.Series> <диаграмм: ColumnSeries ItemsSource = "() Переплетные" DependentValuePath = "X" IndependentValuePath = "Y" /> </ диаграмм: Chart.Series> </ диаграмм: Chart.DataContext> </ диаграмм: Диаграмма>
Регистрация
Совершено в ChartMetadata.cs с следующий код:
(ChartDefaultInitializer))); b.AddCustomAttributes (новый FeatureAttribute (ЪуреоЕ (ChartDefaultInitializer)));
Ссылки
См. ниже скриншоте:
Хотя DefaultInitializer определяется в версии 3.5 Microsoft.Windows.Design.Interaction.dll (в% DevEnvDir% \ PublicAssemblies, т.е. C: \ Program Files \ Microsoft Visual Studio 9.0 \ Common7 \ IDE \ PublicAssemblies на 32bit Windows), то не поддерживается Blend2 или Visual Studio 2008 для Silverlight. Она поддерживается Blend3 и Visual Studio 2010, но они оба перейти на новую версию Microsoft.Windows.Design *. DLL (3.7 Blend 3 просмотра, 4,0 для Blend 3 RTM и Visual Studio 2010), так что нам нужно связать с новая версия MWDs. Пожалуйста, смотрите до должности Как написать Silverlight Дизайн времени для всех дизайнеров: Visual Studio 2008, Blend 2; Blend 3, а также Visual Studio 2010 для получения дополнительной информации.
Пожалуйста, также заметить, что ссылка на System.Windows.dll Silverlight является псевдонимом, и PointCollection специально позвал для Silverlight 1, а не в WPF. С WPF и Silverlight имеют много классов в том же имен, важно, что Silverlight типов, а не в WPF, используются при создании ModelItem и ModelProperty по умолчанию для инициализации Silverlight контроля.
Коллекции
Обратите внимание на скриншот ниже, что, хотя все остальные стоимости имущества могут быть установлены через ModelProperty.SetValue:
Chart.Series имеет тип коллекции (Собрание <Series>), поэтому его стоимость должна быть установлена первая создания ModelItem через ModelFactory.CreateItem на величину, а затем добавить создал ModelItem через ModelProperty.Collection.Add. В противном случае, даже несмотря на правильное XAML может быть получена, Blend не будет обновляться, чтобы сделать контроль Диаграмма правильно, нужно перезагрузить страницу, чтобы он отображается неправильно.
ChartDefaultInitializer.cs
alias Silverlight; using System.Windows.Controls.DataVisualization.Charting; using System.Windows.Controls.Design.Common; using Microsoft.Windows.Design.Metadata; using Microsoft.Windows.Design.Model; using SSW = Silverlight::System.Windows; using SSWD = Silverlight::System.Windows.Data; using SSWM = Silverlight::System.Windows.Media; namespace System.Windows.Controls.DataVisualization.Design { /// <summary> /// Default initializer for chart. /// </summary> internal class ChartDefaultInitializer : DefaultInitializer { /// <summary> /// Sets the default property values for chart. /// </summary> /// <param name="item">Chart ModelItem.</param> public override void InitializeDefaults(ModelItem item) { string propertyName; // <Charting:Chart Title="Chart Title"> propertyName = Extensions.GetMemberName<Chart>(x => x.Title); item.Properties[propertyName].SetValue(Properties.Resources.ChartTitle); // <Charting:Chart.DataContext> // <PointCollection> // <Point X="1" Y="10" /> // <Point X="2" Y="20" /> // <Point X="3" Y="30" /> // <Point X="4" Y="40" /> // </PointCollection> // </Charting:Chart.DataContext> SSWM::PointCollection defaultItemsSource = new SSWM::PointCollection(); for ( int i = 1; i <= 4; i++) { defaultItemsSource.Add( new SSW::Point(i, 10 * i)); } propertyName = Extensions.GetMemberName<Chart>(x => x.DataContext); item.Properties[propertyName].SetValue(defaultItemsSource); // <Charting:Chart.Series> // <Charting:ColumnSeries ItemsSource="{Binding}" // DependentValuePath="X" // IndependentValuePath="Y" /> // </Charting:Chart.Series> ModelItem columnSeries = ModelFactory.CreateItem(item.Context, typeof (ColumnSeries)); propertyName = Extensions.GetMemberName<ColumnSeries>(x => x.ItemsSource); columnSeries.Properties[propertyName].SetValue(ModelFactory.CreateItem(columnSeries.Context, typeof (SSWD::Binding))); propertyName = Extensions.GetMemberName<ColumnSeries>(x => x.DependentValuePath); columnSeries.Properties[propertyName].SetValue( "X" ); propertyName = Extensions.GetMemberName<ColumnSeries>(x => x.IndependentValuePath); columnSeries.Properties[propertyName].SetValue( "Y" ); propertyName = Extensions.GetMemberName<Chart>(x => x.Series); item.Properties[propertyName].Collection.Add(columnSeries); } } } / / (C) Copyright Microsoft Corporation. / / Этот источник может быть Microsoft Public License (Ms-PL). / / См. http://go.microsoft.com/fwlink/?LinkID=131993 для деталей. / / Все другие права защищены. внешних Silverlight псевдоним, использования System.Windows.Controls.DataVisualization.Charting, использования System.Windows.Controls.Design.Common, использования Microsoft.Windows.Design.Metadata, использования Microsoft.Windows.Design.Model; SSW использованием Silverlight =:: System.Windows, использования SSWD = Silverlight:: System.Windows.Data, использования SSWM = Silverlight:: System.Windows.Media; имен System.Windows.Controls.DataVisualization.Design (/ / / <резюме > / / / по умолчанию для инициализации карты. / / / </ резюме> внутренний класс ChartDefaultInitializer: DefaultInitializer (/ / / <summary> / / / Устанавливает значения свойств графика. / / / </ резюме> / / / < параметр имя = "пункт"> Chart ModelItem. </ параметр> общественного переопределить InitializeDefaults недействительными (пункт ModelItem) (строки ргорегЬуЫате / / <Charting:Chart Title="Chart Title"> ргорегЬуЫате = Extensions.GetMemberName <Chart> (х = > x.Title); item.Properties ргорегЬуЫате] [. SetValue (Properties.Resources.ChartTitle) / / <Charting:Chart.DataContext> / / <PointCollection> / / <точка X = "1" Y = "10" /> / / <Point X="2" Y="20" /> / / <Point X="3" Y="30" /> / / <Point X="4" Y="40" /> / / </ PointCollection> / / </ диаграмм: Chart.DataContext> SSWM:: PointCollection defaultItemsSource = новый SSWM:: PointCollection (), для (INT = 1; я <= 4; я + +) (defaultItemsSource.Add (новый SSW:: Point (я, я * 10));) = ргорегЬуЫате Extensions.GetMemberName <Chart> (х => x.DataContext); item.Properties ргорегЬуЫате] [. SetValue (defaultItemsSource); / / <диаграмм: Диаграмма. Серия> / / <Charting:ColumnSeries ItemsSource="{Binding}" // DependentValuePath="X" // IndependentValuePath="Y" /> / / </ диаграмм: Chart.Series> ModelItem columnSeries = ModelFactory.CreateItem (item. Контекст, ЪуреоЕ (ColumnSeries)); ргорегЬуЫате = Extensions.GetMemberName <ColumnSeries> (х => x.ItemsSource); columnSeries.Properties ргорегЬуЫате] [. SetValue (ModelFactory.CreateItem (columnSeries.Context, ЪуреоЕ (SSWD:: Переплетные)) ); ргорегЬуЫате = Extensions.GetMemberName <ColumnSeries> (х => x.DependentValuePath); columnSeries.Properties ргорегЬуЫате] [. SetValue ("X"); ргорегЬуЫате = Extensions.GetMemberName <ColumnSeries> (х => x.IndependentValuePath); columnSeries.Properties [ргорегЬуЫате]. SetValue ("Y"); ргорегЬуЫате = Extensions.GetMemberName <Chart> (х => x.Series); item.Properties [ргорегЬуЫате]. Collection.Add (columnSeries);)))

.png)








Знаете ли вы каким-либо образом обеспечить обратную связь для пользователя, для длительных операций с DefaultInitializer (я имею в виду что-то вроде показывает прогресс бар)?
Проблема в том, что я могу показать прогресс бар в начале и спрятать его в конце метода InitializeDefaults, но этот метод потребляют лишь небольшую часть времени, необходимого для получения контроля.
Великий сообщения!
@ Мирослав Paskov
Привет Мирослав,
В последней версии (RTM Silverlight 3 и Инструментарий июля 2009), Вы уже можете делать пункт 1 с аккордеоном, TreeView, Expander, DatePicker и т.д.: выбранный элемент будет шоу. У меня в блоге объяснить, как это сделать, но не удосужился закончить еще. Что касается связи и т.д. меню, ждать следующего релиза Toolkit. Я думаю, что я выполнил все поведение время разработки для Silverlight TabControl что вы видите в WPF. Я блог о ее, когда она освободится.
Спасибо,
Нин-
Привет Нин,
Великий сообщения! Пожалуйста, имейте в их наступлении. Я искал в расширяемости Blend и у меня несколько вопросов:
1. Как обеспечить взаимодействие по умолчанию TabControl? Пользователь может переключаться TabItems, выбрав их с помощью мыши. Кажется, что это возможно, даже в Blend 2.
2. Как мы можем добавить контекстное меню, похожие на "Добавить TabItem" для TabControl? Опять же, это, кажется, для Blend 2.
Мирослав