Today at MVP Summit 2010, one of the things I discussed with the MVPs was the concept of XamlSchema. To leverage my already done work, and to share with all of you, my XAML friends, I’m following up my talk with a post that goes into that area.
All XAML systems have a way that they figure out XamlSchema. [MS-XAML]’s section 3 is “XAML Schema Information set” which defines Schema, XamlType, and XamlMember. .NET 4’s XAML stack exposes a set of apis that closely mirror that information about types and members.
XamlSchemaContext
A XamlSchemaContext is the object that retrieves (and usually caches) type/member information for the purposes of understanding XAML behavior for Load or Save or other.
There are 3 interesting flavors of XamlSchemaContexts today:
- WPF optimized context: XamlReader.GetWpfSchemaContext() – These XamlTypes/XamlMembers are optimized to avoid reflection in many cases for type/member information and for actions like “New”, “Set”, “Get”, “Add”, etc…
- General purpose .NET context: new XamlSchemaContext() – These XamlTypes/XamlMembers are built on top of Reflection APIs for type/member information and for actions like “New”, “Set”, “Get”, “Add”, etc…
- Silverlight context: new SilverlightSchemaContext() //from XamlToolkit - code.msdn.com/xaml - These XamlTypes/XamlMembers are built on top of Reflection APIs for type/member information and for actions like “New”, “Set”, “Get”, “Add”, etc… (but they know that the Silverlight has a subset of “XamlTypeInformation attributes and interfaces” that .NET Framework has – and adapt. For example ContentPropertyAttribute in .NET 4 is in System.Xaml.dll, but it is in System.Windows.dll in Silverlight 2-4.)
Goal for XamlSchemaContext
Have one way for XAML systems to understand XamlSchema for types. Have one way for XAML systems to provide XamlSchema in other type systems (CLR, Silverlight, NativeCode, JavaScript, Java, etc…)
Some Scenarios for XamlSchemaContexts
Given a XamlSchemaContext, there are a few interesting things that you can do with it:
Code Sample
I’ve posted this project at http://robrelyea.com/demos/xamlSchemaExplorer
1: using System;
2: using System.Collections.Generic;
3: using System.ComponentModel;
4: using System.Windows.Markup;
5: using System.Xaml;
6: using System.Text;
7:
8: namespace XamlSchemaExplorer
9: {
10:
11: public class Program
12: {
13: static void Main(string[] args)
14: {
15: XamlSchemaContext schemaContext = new XamlSchemaContext();
16: XamlType xamlType = schemaContext.GetXamlType(typeof(SampleClass));
17:
18: StringBuilder sb = XamlUtilities.GetStringRepresentationOfXamlType(xamlType);
19: string output = sb.ToString();
20: Console.WriteLine(output);
21: }
22: }
23:
24: #region SampleClass class definition
25: [ContentProperty("Bar")]
26: public class SampleClass
27: {
28: [TypeConverter(typeof(BarConverter))]
29: public bool Bar { get; set; }
30:
31: public int Foo { get; set; }
32:
33: public string Baz { get; set; }
34:
35: private List<int> _integers;
36: public List<int> Integers
37: {
38: get
39: {
40: if (_integers == null)
41: {
42: _integers = new List<int>();
43: }
44: return _integers;
45: }
46: }
47: }
48: #endregion
49:
50: #region TypeConverters
51: public class BarConverter : TypeConverter
52: {
53:
54: }
55: #endregion
56:
57: public static class XamlUtilities
58: {
59: public static StringBuilder GetStringRepresentationOfXamlType(XamlType xamlType)
60: {
61: StringBuilder sb = new StringBuilder();
62:
63: sb.AppendLine(xamlType.Name);
64: XamlMember contentProperty = xamlType.ContentProperty;
65:
66: foreach (var xamlMember in xamlType.GetAllMembers())
67: {
68: sb.AppendFormat(" {0} {1} {2}\n",
69: xamlMember.Type.IsGeneric ? XamlUtilities.GetGenericName(xamlMember.Type) : xamlMember.Type.Name,
70: xamlMember.Name,
71: xamlMember.IsReadOnly ?
72: " { get; } " : " { get; set; }");
73: if (xamlMember.TypeConverter != xamlMember.Type.TypeConverter)
74: {
75: sb.AppendLine(" ** Converter is " + xamlMember.TypeConverter.Name);
76: }
77: if (xamlMember == contentProperty)
78: {
79: sb.AppendLine(" ** This is the ContentProperty");
80: }
81: }
82: return sb;
83: }
84:
85: public static string GetGenericName(XamlType xamlType)
86: {
87: string typeName = xamlType.Name;
88: typeName += "<";
89: int typeArgCount = 0;
90: foreach (var typeArg in xamlType.TypeArguments)
91: {
92: if (typeArgCount > 0)
93: {
94: typeName += ",";
95: }
96:
97: if (typeArg.IsGeneric)
98: {
99: typeName += GetGenericName(typeArg);
100: }
101: else
102: {
103: typeName += typeArg.Name;
104: }
105: }
106: typeName += ">";
107: return typeName;
108: }
109: }
110: }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
This outputs the following to the command line:
1: SampleClass
2: Boolean Bar { get; set; }
3: ** Converter is BarConverter
4: ** This is the ContentProperty
5: Int32 Foo { get; set; }
6: String Baz { get; set; }
7: List<Int32> Integers { get; }
8:
9: Press any key to continue . . .
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Would love to understand your questions/issues
Please let us know what you think…