Welcome to WindowsClient.net | Sign in | Join

Rob Relyea - XAMLified

WPF, Silverlight and XAML

Syndication

Sponsors





  • advertise here
XamlSchemaContext/XamlType/XamlMember – a command line example

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:

  1. 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…
  2. 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…
  3. 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…
Published Wednesday, February 17, 2010 4:36 PM by Rob_Relyea
Filed under: ,

Comments

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 9:40 AM

Hi Rob,

As I understand, creating a custom XamlSchemaContext could be a way to make Xaml content integrate with an IoC, isn't it?

I can imagine a scenario where you can then write something like :

<Foo>

 <Foo.Bar><IBar /></Foo.Bar>

</Foo>

With IBar being an interface that is resolved by the IoC. Same thing could apply with types without default constructor whose dependencies could be injected by the IoC-enabled schema context.

If you confirm that it is doable, I'll make a sample of a Unity-enabled Xaml Schema Context.

# Dew Dump &ndash; February 17, 2010 | Alvin Ashcraft&#039;s Morning Dew@ Thursday, February 18, 2010 10:08 AM

Pingback from  Dew Dump &ndash; February 17, 2010 | Alvin Ashcraft&#039;s Morning Dew

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 10:48 AM

Simon-

You could map from a XamlType of IBar to another XamlType a couple of different ways.

Some options:

1) make a XamlSchemaContext that given an interface, picks another type to give out. But I think that would be a bit strange...consider the next option.

2) let XamlXmlReader work with a normal XamlSchemaContext, but analyze the XamlNodes created in a XamlNodeLoop (search for that term on the web) and replace them before the XamlObjectWriter sees them. create a function called XamlServicesWithIOC.Load(...) or similar that provides this functionality.

3) there are likely other options for doing this also...but not with that markup.

a) you could have a markupextension <Foo.Bar><PleaseCreateA><IBar/></PleaseCreateA></Foo.Bar> -- that would be able to work in existing XAML loading call paths, but the markup isn't as nice. Use XamlDeferringLoader like FrameworkTemplate in WPF4 uses it, to get the content inside PleaseCreateA as a list of XAML Nodes.

b) other?

Thanks, Rob

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 12:00 PM

Well the problem with solution 2 is that you do only type mapping and not really Dependency Injection (for example the concrete implementation of IBar could depends on IOtherService that is also registered in the IoC container and take it as a constructor parameter). That's why XamlSchemaContext seems very good to me.

by Simon

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 12:41 PM

Simon-

Let's talk in person today...since you are still at the MVP Summit.

Thanks, Rob

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 1:13 PM

Another alternative is to override XamlTypeInvoker.CreateInstance, and have it crate an instance of the appropriate concrete type at load time. I think that makes a cleaner decoupling between the XAML and the dependency injection.

by Dan Glick

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Thursday, February 18, 2010 2:42 PM

@ Dan : I just wrote a sample with a custom XamlSchemaContext that creates overriden XamlTypeInvokers when it finds a non constructible type. It works very well and the code is surprisingly pretty simple.

I'll put it on my blog as soon as I have the time to write something.

by Simon

# Inversion of Control (IOC) with XAML@ Sunday, February 21, 2010 5:55 PM

I met Simon Ferquel this week at the 2010 MVP Summit. I gave a talk about XAML on Wednesday, and later

# Social comments and analytics for this post@ Sunday, February 21, 2010 10:06 PM

This post was mentioned on Twitter by rrelyea: blogged about XamlSchemaContext/XamlType/XamlMember with a code sample...part of my #MVP10 #XAML talk. http://tinyurl.com/ybolmxm

# Windows Client Developer Roundup for 2/22/2010@ Monday, February 22, 2010 1:12 AM

This is Windows Client Developer roundup #12. I’ve just returned from the MVP summit and some meetings

# Windows Client Developer Roundup for 2/22/2010@ Thursday, March 11, 2010 4:14 PM

This is Windows Client Developer roundup #12. I’ve just returned from the MVP summit and some meetings

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Tuesday, April 13, 2010 9:13 AM

Hi, I'm developing a WPF solution with support for dynamic dependency properties,

this means registration, set value and data binding all in one XAML fragment.

In order to get it done, I need to define my own XamlSchemaContext,

to overload XamlType and allow the dynamically created DP as XamlMember.

Further on I overload XamlObjectWriter.OnSetValue to support setting the value in XAML.

It all goes well - the value is set correctly, but the only way to use my own XamlSchemaContext seems to require to omit XamlReader and use XamlServices.Transform(..).

This leads to a non-functional DataBinding.

Do you have an idea?

Thanks in advance

Nikolay Nikolov

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Tuesday, May 11, 2010 3:35 PM

Miroslav-

We are trying to update the SL XSC in the next few weeks...and we'll be able to publish some assembly loading samples with that.

The schemaContext has a bunch of fixes, so telling you how to work with the November one may not be that useful, and would delay the team from getting the new one out the door.

Sorry for the trouble...help is on the way soon.

Thanks, Rob

# re: XamlSchemaContext/XamlType/XamlMember – a command line example@ Monday, June 28, 2010 3:13 AM

I agree with the IBar being an interface could also be applied with types without default constructor whose dependencies could be injected by the IoC-enabled schema context.

# horoscopes@ Friday, December 23, 2011 7:44 PM

Pingback from  horoscopes

# horoscopes@ Friday, December 23, 2011 8:22 PM

Pingback from  horoscopes

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Page view counter