In Depth Longhorn/XAML Property Aliasing

[*Note, this is compiled and running on the PDC builds of Whidbey and Longhorn, respectively]

This is an expansion on my old post , with updates in red

By writing a transformer, you'll make the UIElements more able to accept other types of data than the default. Take for example the "Text" property of a Button control: normally, this will accept string values. You can make your control validate accepted values through a DataTransformer for one example. You could display different UI "feels" based on your data for another. Say you're making a Auction Application; you can bind the background of a Canvas to a transformed price. Your DataTransformer can make the lower priced items Green (or even better, the ones most matching your search criteria). I can think of many great uses for this! 

This is called from the XAML, when the code is databound. The bind statement itself transforms the data, so the control gets the output of the transformer.

Now this can get very interesting.  Let's take the sample code in this zip file for example, and more completely in this second sample (the “B“ sample)

There's an XMLDataSource, which provides data to bind any controls in that canvas to, along with the DataContext in which to bind.  In this example, we're binding the SimpleText.Text property with the Title tag of the Book path of the DataSource.

 <SimpleText Canvas.Top="35px" Canvas.Left="35px" Width="300px" Height="30px"    ID="boundtext">
            <SimpleText.Text>
                <Bind Path="Title"/>
            </SimpleText.Text>           
        </SimpleText>

Now what if we want to transform this data based on certain rules  (See the first paragraph for some ideas)? This is where the transformer comes into play. We'll declare a new transformer in the resources: (nb: be sure to include the namespace, unlike some samples floating around the docs.  If you don't include the namespace, it won't use the transformer)

<TransformerSource def:Name="MyTransformerReference" TypeName="StylePlayground.SpanishTransformer"/>

Actually, this is mandatory;

Using "Longhorn" markup language (code-named "XAML"), a transformer class must be an application resource. If the transformer code is written as code-behind inside the same application, the resource is created as a TransformerSource element. This TransformerSource element allows you to avoid a circular reference problem with trying to reference a custom element inside resources before the transformer class itself is compiled further down in the code. Then, to specify the transformer within a binding, set the transformer attribute to the resource name of your TransformerSource element in resources.
http://longhorn.msdn.microsoft.com/lhsdk/connecteddata/tasks/transformbounddata.aspx

So how do we actually use this transformer in a control you ask? Easy; just sent the Transformer property in the binding statement as so:

<SimpleText Canvas.Top="70px" Canvas.Left="35px" Width="300px" Height="30px"   ID="mytransformedtext">
            <SimpleText.Text>
                <Bind Path="Title" Transformer="{MyTransformerReference}"/>
            </SimpleText.Text>           
        </SimpleText>  

Now all that's left is to write the DataTransformer.  For that, we go to our code-behind, using your .net language of choice (mine is C#) and implement IDataTransformer (Don't forget to import the MSAvalon.Windows.Data namespace)

public class SpanishTransformer: IDataTransformer
 {
  public object Transform(object o, DependencyProperty dp, System.Globalization.CultureInfo culture)
  {
   string dataBoundText = (string)o;
   Translate t = new Translate();   

   switch (dp.Name)
   {
    case "Text" :
     return t.TranslateLanguage("en|es", dataBoundText); break;

    case "Foreground" :
     return "Red"; break;

    default :
     return o; break;
   }
  }
  public object InverseTransform(object o, System.Reflection.PropertyInfo info, System.Globalization.CultureInfo culture)
  {
   return null;
  }
 }

And there you have it.  The UI actually localizes itself.  The wonders of the datatransform are readily evident.

 

Now lets delve into what I did wrong with this example:

    • Using a web service to show UI elements is bad with a capital-BAD.
    • The web service call isn't even asynch
    • Absolute positioning of UI elements (that's what flow elements are for)
    • The DataTransformer is in the same .cs file as the 2nd half of the UI partial class

Well, it's just a sample anyway, but I thought I'd mention that even though this is just an example.

 

No Comments