Modification Initializer modèle par défaut pour les contrôles et Silverlight
Introduction
Cela fait partie de la série sur la mise en œuvre caractéristique de conception du temps dans Silverlight Toolkit . Ce message utilise l'initialiseur défaut graphique pour illustrer comment mettre en œuvre initialisation par défaut pour les contrôles Silverlight, et d'expliquer l'architecture sous-jacente de montage du modèle.
Expérience
Si vous installez Silverlight 3 Toolkit en Mars 2009 Communiqué , vous pouvez faire glisser le contrôle graphique à partir de la bibliothèque d'actifs Blend et déposez-le sur la surface de designer, et vous avez un tableau bien initialisé et rendu:
Vous pouvez en lire plus à ce sujet lors des précédentes post Caractéristiques Silverlight Toolkit Design Time: Mise à jour Mars Presse 2009 .
Architecture
DefaultInitializer
Il est en fait assez simple de fournir une initialisation par défaut pour un contrôle Silverlight:
- mettre en œuvre une sous-classe de DefaultInitializer , et substituer sa InitializeDefaults fonction
- associer la classe initialisation par défaut avec la classe de contrôle via un FeatureAttribute
Ci-dessous capture d'écran montre la mise en œuvre de la classe de base abstraite DefaultInitializer, et d'autres classes dans l'espace de noms Microsoft.Windows.Design.Model qui seront abordés prochainement:
L'initialisation est fait en remplacement InitializeDefaults, et le résultat est sérialisé dans XAML. Donc la première étape dans la mise en œuvre d'un initialiseur de valeur par défaut est de définir le choix xaml à produire.
Modification du modèle
Une fois le résultat xaml est définie, je souhaite qu'il y est une méthode de niveau supérieur d'abstraction / cela ne ferait que prendre le XAML. Mais malheureusement, nous devons utiliser un niveau beaucoup plus faible (donc plus souple et plus puissante) API impératif appelé édition modèle qui se compose de classes comme ModelItem , ModelProperty , ModelEvent , ModelFactory et ModelService . La page MSDN édition modèle de l'architecture donne un aperçu de base:
Votre moment de la conception mise en œuvre interagit avec l'exécution des contrôles en temps si une interface de programmation appelé le modèle d'édition. Les objets en cours de conception sont appelés des objets modifiables.
Vos commandes sont définis dans Extensible Application Markup Language (XAML). Vous mettez à jour le code XAML pour vos contrôles par programmation en utilisant le modèle d'édition.
Modèle, Wrapper, et de
Le modèle d'édition se compose de trois sous-unités fonctionnelles: un modèle, un wrapper publique qui fait abstraction du modèle, et une vue qui représente l'interface utilisateur (UI) du modèle. Le modèle et la vue sont séparés, mais l'emballage et le modèle sont étroitement liés. L'illustration suivante montre la relation entre les trois sous-unités.
Environnement de création utilise l' ModelItem type à communiquer avec le modèle sous-jacent. Toutes les modifications sont apportées aux ModelItem emballages, qui affectent le modèle sous-jacent. Cela permet au modèle d'être simple. Les ModelItem wrappers gérer fonctionnalités de conception complexes, telles que le support des transactions, défaire le suivi, et les notifications de changement.
Ci-dessous le diagramme de classes peut aider à expliquer les interactions entre les classes de base du modèle d'édition:
Utilisez-dessous XAML comme un exemple:
- ModelItem: supposons élément variable est la ModelItem pour le contrôle Button ci-dessus,
- Nom est sauvegardé comme attribut x: Name en XAML: item.Name = "Button" est conservé dans XAML x: Name = "Button".
- ItemType est l'objet Type du contrôle sous-jacent, et décide de l'étiquette utilisée en XAML: item.PropertyType == tyepof (Button), et la balise XAML est <Button />.
- Propriétés est la collection de propriétés, enveloppés dans le type ModelProperty, de la commande sous-jacente. Par exemple: item ["ClickMode"] = ClickMode.Release sera persisté en XAML comme ClickMode = "sortie".
- Contenu représente la propriété Content défini dans ContentControl (et hérité par ses sous-classes): item.Content est le représentant ModelItem l'objet Rectangle.
- Source: quand un ModelItem représente un élément qui est une propriété d'un autre élément, la source est le wrapper ModelProperty de cette propriété. Par exemple, item.Content.Value.Source == item.Content / / le rectangle.
- Événements représente la collection d'événements du contrôle sous-jacent, enveloppés dans le type ModelEvent. D'après mon expérience de débogage, il est toujours nulle, de sorte qu'il semble bien Événements n'est pas encore supporté par Blend3 pour Silverlight3 encore.
- Parent est le parent de la logique du contrôle sous-jacent, enveloppé dans le type ModelItem. ex: Item.Parent est le ModelItem pour la grille.
- Root est le wrapper pour ModelItem visuel racine, ex: item.Root représente le UserControl.
- ModelProperty: supposons prop variable est la ModelProperty pour Button.Content, prop ie = item.Content,
- Nom est le nom de la propriété du contrôle sous-jacent. Il est conservé dans XAML comme nom d'attribut. ex: prop.Name == "Contenu".
- PropertyType est l'objet Type de la propriété du contrôle sous-jacent de cet objet ModelProperty représente. ex: prop.PropertyType = typeof (objet).
- AttachedOwnerType est l'objet Type du contrôle qui définit d'abord la propriété de cet objet ModelProperty représente. ex: prop.AttachedOwnerType == typeof (ContentControl) / / note: pas touche.
- La valeur est la valeur de la propriété du contrôle sous-jacent, enveloppé dans le type ModelItem. ex: prop.Value est le représentant ModelItem l'objet Rectangle.
- Parent est le contrôle, enveloppé dans le type ModelItem, dont la propriété appartient à. ex: prop.Parent == élément.
- ModelEvent: comme mentionné ci-dessus, item.Events est toujours nulle, de sorte qu'il ne semble pas que ModelEvent est pris en charge dans Blend3 pour Silverlight3 encore. Mais supposons que cela fonctionne, et evt variable est la ModelEvent pour Button.Click, c.-à-evt = item.Events ["Click"],
- Nom est le nom de l'événement. ex: evt.Name == "Cliquez sur".
- EventType est le type du délégué événement, ex: evt.EventType == typeof (RoutedEventHandler).
- Gestionnaires est la collection de chaînes de gestionnaires d'événements, ex: evt.Handlers = new String [] {"Button_Click"} sera sauvegardé comme Click = "Button_Click". Remarque: ce n'est que pure spéculation, car ModelEvent n'est pas encore supporté, et je ne sais pas si / quand / comment il sera pris en charge pour Silverlight.
- Parent est le contrôle, enveloppé dans le type ModelItem, dont cet événement appartient. ex: evt.Parent == élément.
Exécution
La valeur par défaut graphique de classe initialiseur ChartDefaultInitializer est mis en œuvre dans ChartDefaultInitializer.cs, et enregistré dans ChartMetadata.cs. Les deux fichiers se trouvent dans des Controls.DataVisualization.Toolkit.Design.csproj Silverlight.Controls.Design.sln. S'il vous plaît lire avant après la conception d'entité Temps de mise en œuvre dans Silverlight Toolkit pour plus d'informations.
Résultat XAML
Comme la première étape, définir le xaml résultat à être produite par ChartDefaultInitializer:
Title ="Chart Charting <: Titre du graphique = "Graphique
Inscription
Fait à ChartMetadata.cs avec le code suivant:
(ChartDefaultInitializer))); b.AddCustomAttributes (FeatureAttribute nouvelle (typeof (ChartDefaultInitializer)));
Références
Voir ci-dessous capture d'écran:
Même si DefaultInitializer est défini dans la version 3.5 de Microsoft.Windows.Design.Interaction.dll (sous% DevEnvDir% \ PublicAssemblies, par exemple c: Program Files \ Microsoft Visual Studio 9.0 \ Common7 \ IDE \ PublicAssemblies sur Windows 32 bits), il est pas pris en charge par Blend2 ou Visual Studio 2008 pour Silverlight. Il est soutenu par Blend3 et Visual Studio 2010, mais ils ont tous deux dll passage à version plus récente d'* Microsoft.Windows.Design. (3,7 pour Blend 3 Preview, 4.0 pour Blend 3 RTM et Visual Studio 2010), nous avons donc besoin de se lier aux la nouvelle version de MWDs. S'il vous plaît voir avant poster Comment écrire Silverlight moment du design pour tous les concepteurs: Visual Studio 2008, Blend 2; Blend 3, et Visual Studio 2010 pour plus d'informations.
S'il vous plaît également remarquer que la référence à System.Windows.dll Silverlight est un alias, et le PointCollection est spécifiquement appelé à être le Silverlight, pas WPF. Depuis part WPF et Silverlight beaucoup de classes dans les espaces de noms mêmes, il est important que les types de Silverlight, WPF pas, sont utilisés dans la création et ModelItem ModelProperty dans l 'initialisation par défaut pour les contrôles Silverlight.
Collections
S'il vous plaît noter ci-dessous capture d'écran que si toute la valeur d'autres biens peut être réglée via ModelProperty.SetValue:
Chart.Series est du type de collection (Collection <Series>), donc sa valeur doit être réglé en créant d'abord une ModelItem via ModelFactory.CreateItem pour la valeur, puis ajoutez le ModelItem créé via ModelProperty.Collection.Add. Sinon, même si la bonne xaml peut être généré, Blend ne sera pas rafraîchir pour rendre le contrôle de la carte correctement, vous devez recharger la page pour l'avoir rendu correctement.
ChartDefaultInitializer.cs
alias / / (C) Copyright Microsoft Corporation. / / Cette source est soumis à la Microsoft Public License (Ms-PL). / / S'il vous plaît voir http://go.microsoft.com/fwlink/?LinkID=131993 pour plus de détails. / / Tous les autres droits sont réservés. alias extern 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); = Silverlight System.Windows ::; utilisant SSWD = Silverlight :: System.Windows.Data; utilisant SSWM = Silverlight :: System.Windows.Media; espace de noms System.Windows.Controls.DataVisualization.Design {/ / / <summary> / . / / par défaut d'initialisation pour le graphique / / / </ summary> ChartDefaultInitializer classe interne:. DefaultInitializer {/ / / / / / <summary> Définit les valeurs de propriété par défaut pour le tableau / / / </ summary> / / / <param nom . = "item"> Graphique ModelItem </ param> public override void InitializeDefaults (point ModelItem) {PropertyName chaîne; / / <Charting:Chart Title="Chart Title"> propertyName = Extensions.GetMemberName <Chart> (x => x . Titre); 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 (nouveau SSW: : Le 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> ColumnSeries ModelItem = ModelFactory.CreateItem (item.Context, typeof (ColumnSeries)); propertyName = Extensions.GetMemberName <ColumnSeries> (x => x.ItemsSource); ); propertyName = Extensions.GetMemberName<Chart>(x => x.Series); item.Properties[propertyName].Collection.Add(columnSeries); } } } propertyName = Extensions.GetMemberName <ColumnSeries> (x => x.DependentValuePath); columnSeries.Properties [propertyName] SetValue ("X");. propertyName = Extensions.GetMemberName <ColumnSeries> (x => x.IndependentValuePath); ColumnSeries. Propriétés [propertyName] SetValue ("Y");. propertyName = Extensions.GetMemberName <Chart> (x => x.Series); item.Properties [propertyName] Collection.add (ColumnSeries);.}}}

.png)








Commentaires récents