Welcome to WindowsClient.net | Sign in | Join

Rob Relyea - XAMLified

WPF, Silverlight and XAML

February 2010 - Posts

Rob Update – Looking forward

I’m still spending time on .NET 4/VS 2010, but since January, I’ve also been doing more forward looking thinking. We have a long list of important things to do…I’m itching to engage on several fronts…lots of good stuff to do.

Fun times!

WPF: Feature Suggestions

  • There is a WPF Feature Suggestions site now! You get 10 votes…don’t waste them before you see all the ideas. We’re about to ship what I think is a great WPF 4 release…and we’re taking this opportunity to connect with you, the XAML UI heads out there, to understand your wishes, needs and priorities. Vote early, vote often!

Tools: WPF & Silverlight Designer in VS 2010

XAML: XAML for Config

Windows Phone 7 Series

.NET Framework

image_2[1]

Setup: WiX

  • Excited to see Rob’s announcement. I, too, like numbers like 11, 22, 33, etc… Happy belated 33rd bday Rob…and I’m happy about your new day job.
  • WiX v3.5 supports VS 2010 RC -- Read about the “Harvest” feature (point #3 in Rob Mensching’s post)

Data/Modeling

I met Simon Ferquel this week at the 2010 MVP Summit. I gave a talk about XAML on Wednesday, and later that day blogged one of my samples from the talk: “XamlSchemaContext/XamlType/XamlMember – a command line example”.

He commented on that post with:

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.

by Simon Ferquel

Turns out that subclassing XamlSchemaContext and XamlType seems to have worked quite nicely. See Simon’s “[Xaml] IoC-enabled Xaml parser” The basic idea is the custom schema context returns a XamlType for IBar that says it knows how to be created.  When the XamlObjectWriter calls it to create the IBar, it can find an appropriate IBar to return.

Other Approaches

Other people have accomplished Invesrion of Control other ways…

  • John “Z-Bo” Zabroski uses a custom markup extension. (via comment)
  • I’ll add more links as I find other approaches or comments mention them.
Posted by Rob_Relyea | 6 comment(s)
Filed under: ,

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…
Posted by Rob_Relyea | 10 comment(s)
Filed under: ,

Interesting to see “From NetReflector to XAML” from Craig Sutherland detailing an exploration of using XAML for Config for CruiseControl.NET.

WPF’s XamlReader.Load vs System.Xaml’s XamlServices.Load()

CS: “although from what I understand WPF will still have its own implementation”

RR: WPF 4’s API XamlReader.Load’s goal is to be compatible, yet better, than the WPF 3 version of XamlReader.Load. This call does some special things for WPF (see Mike Shim’s “Use XamlReader.Load for WPF XAML (not XamlServices.Load)” for details. For Config scenarios, XamlServices.Load/Save would be ideal…that is what I do wth XamlPadSample as detailed in “Persistable View Models & XAML for Config

Representing Time

Craig shows the use of a markupextension for Time: {Time 5} or {Time 30, Unit=Minutes}, etc…

A few options to consider (for Interval.Period, SubVersion.Timeout, Project.ModificationDelay, etc…) would be:

  • Keep using the {Time} markupextension. Decent readability…
  • Make those properties of type TimeSpan, which has a type converter that will convert to/from a string – see DoubleAnimation.Duration, for example:

<DoubleAnimation Storyboard.TargetName="MyAnimatedRectangle" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" />

  • Keep those property of type Int32, but use a “A Type Converter Declared on a Property” (see “Strings to Things (or How XAML interprets Attribute Values”) to introduce a TypeConverter than knows how to convert a string representing a time to integers. Similar approach allows UIElement.Height/.Width use “1in”, “96px”, etc…
Posted by Rob_Relyea | 4 comment(s)
Filed under:

Robby Ingebretsen, nerd + artist extraordinaire, just blogged a bit about his plans for taking Kaxaml forward in the WPF 4 and Silverlight 4 era: “Kaxaml Update + Downloads + A Request

He and I had a good chat last week over his plans and some of the ways that .NET 4 can help XAML focused tools for .NET or Silverlight better.

Should be very fun!

Posted by Rob_Relyea | with no comments

I always enjoy understanding Don’s perspectives. This InfoQ interview is interesting as always. Touches on SOAP, XML, XML Schema, M, etc…

InfoQ: Don Box Discusses SOAP, XML, REST and M

Is XML as bad as Don is saying to you?

We can explore other ways to write down the XAML data model (O-M-V + TypeInfo)… John Gossman prototyped JAML (John’s Application Markup Language) the other week with .NET 4’s XAML stack.

if XML isn’t the right thing, we are not stuck with XML…

Posted by Rob_Relyea | 3 comment(s)

XAML has a major problem in v3 that we’ve addressed with a hotfix last year and .NET 4 includes the fix as well.

From KB 968227 article:

Consider the following scenario:

  • You have a computer that uses the English (United States) regional settings.
  • In the Regional and Language Options item in Control Panel, you customize the List separator character in Customize Regional Options dialog box .
  • You create a Windows Presentation Foundation (WPF) application.
  • The application creates a CultureInfo object for the English (United States) culture before WPF starts rendering.

When you start the application, an exception is thrown by the Extensible Application Markup Language (XAML) parser, and then the application crashes.

Posted by Rob_Relyea | 1 comment(s)
Filed under:
Page view counter