Damon Payne: Hand waving software architect

103db signal to noise ratio at < .03% total harmonic distortion
Solution Architect, software developer, geek
Damon Payne at Blogged
2009 Microsoft MVP - Client App Dev
2007 Microsoft MVP - Solution Architecture
 Monday, September 21, 2009

In my last article on View-based navigation, I mentioned that a useful Navigation History module could be built to work in concert.  This article discusses the design and implementation of that module. In this case my design goals are more straightforward:

  1. Allow the size of the navigation history to be set so as to control memory usage
  2. Allow going forwards and backwards in the history
  3. Allow inspection of the navigation history
  4. Allow aspects of navigation history to be bindable

Navigation History

As with the core navigation concepts I went over previously, there is some basic Navigation History built into the Frame class in Silverlight 3.  Since I’ve extended the core navigation concepts I can also add additional hooks for navigation.  As usual, I will first think of my design goals and craft an interface.

public interface INavigationHistory : INotifyPropertyChanged
{
    /// <summary>
    /// How many Views do we want to keep around?
    /// </summary>
    int HistorySize { get; set; }

    /// <summary>
    /// Go back one View, return the next active view
    /// </summary>
    IView GoBack();


    /// <summary>
    /// Go forward one view, return the next active view
    /// </summary>
    /// <returns></returns>
    IView GoForward();

    /// <summary>
    /// Can we go back based on current position?
    /// </summary>
    bool CanGoBack{get;}

    /// <summary>
    /// Can we go forward based on current position
    /// </summary>
    bool CanGoForward{get;}

    /// <summary>
    /// Called by clients to add a view to history
    /// </summary>
    /// <param name="v"></param>
    void Navigated(IView v);

    event Action<IView> NavigatedToView;

    event Action<IView> HistoryItemRemoved;

    /// <summary>
    /// Get the items in the current history, allow a jump to a specific point
    /// </summary>
    ObservableCollection<IView> CurrentHistory { get; }
    

    /// <summary>
    /// Go to a specific View in the history
    /// </summary>
    /// <param name="historyIndex"></param>
    void GoTo(IView v);

    /// <summary>
    /// Removes the most recent item
    /// </summary>
    /// <returns></returns>
    IView Pop();
}

Including INotifyPropertyChanged here means aspects of the navigation history will be bindable: CanGoBack, CanGoForward, and CurrentHistory.  The other parts of the interface should be self explanatory.

Binding to History

Using the previous Audi Fans demo, I can now make the navigation buttons in the lower right hand corner work.

navhist0

The XAML for creating these buttons is fairly simple, note the {Binding} aspects:

<StackPanel Orientation="Horizontal" Grid.Row="2" Margin="5" HorizontalAlignment="Right">
    <TextBlock Style="{StaticResource TextStyle}" >Navigation: </TextBlock>
    <Button x:Name="GoBack" IsEnabled="{Binding Path=History.CanGoBack}" Click="GoBack_Click">
        <Button.Content>
            <TextBlock Style="{StaticResource TextStyle}" Foreground="Black">&lt; Back</TextBlock>
        </Button.Content>
    </Button>                    
    <ComboBox x:Name="JumpCmb" DataContext="{Binding}" ItemsSource="{Binding Path=HistoryItems}" SelectedItem="{Binding Path=CurrentViewName, Mode=TwoWay}" Margin="10,0,10,0" Width="250" >                        
    </ComboBox>                     
    <Button x:Name="GoForward" IsEnabled="{Binding Path=History.CanGoForward}" Click="GoForward_Click">
        <Button.Content>
            <TextBlock Style="{StaticResource TextStyle}" Foreground="Black">Forward &gt;</TextBlock>
        </Button.Content>
    </Button>
</StackPanel>

In order to satisfy these bindings, the Navigation History implementation has been added to the MainViewModel for the front page.  You will note that I’m not binding directly to the History.CurrentHistory but that some additional fields have been added to MainViewModel:

ObservableCollection<string> _histItems;

/// <summary>
/// Silverlight crashes if you use a Page (IView) as a binding source.  Lame.
/// </summary>
public ObservableCollection<string> HistoryItems
{
    get
    {
        return _histItems;   
    }        
}


string _currentViewName;

public string CurrentViewName
{
    get { return _currentViewName; }
    set
    {                
        if (value != _currentViewName)
        {
            _currentViewName = value;
            OnPropertyChanged("CurrentViewName");

            if (_viewMap.ContainsKey(value))
            {   
                Navigation.GoTo(_viewMap[value]);
            }
        }
    }
}

Pit of failure: Silverlight does not seem to like having a Page object as a binding source except when doing Element binding.  This may be a low level implementation detail that’s just not supported, or it may be because the Pages in question are not visible and this causes some fundamental failure.

So there is a layer that maps IView names back to the INavigationHistory because Silverlight binding doesn’t like binding to a visual element that is not currently visible.

Conclusion

That’s pretty much it for Navigation History, be sure to read the previous article if you’d like to see how it fits in with everything else.  There are other directions you could take this, obviously.  If you are using some kind of Region manager you could scope the navigation to each region.  If you are concerned about memory usage, you could create a scheme to use WeakReferences and provide hooks to save just the ViewModel of an IView so that the IView itself could be reconstructed later. 

The updated source code for the HandWaver.AG guidance projects can be found here.



Monday, September 21, 2009 6:17:04 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, September 16, 2009

 

Silverlight 3 ships with a Navigation mechanism.  A control that extends Page can be stored inside the Frame control as content, and Navigation from Page to Page is done by specifying the URI of the target Page.  This mechanism includes navigation history and the ability to go forwards and backwards through said history.  I would, however, like a slightly different programming model around application navigation.

Design goals:

  1. I would like to be able to navigate to a new “screen” from within various places such as Presenters or Commands
  2. I do not want to have to configure each new View I add to the system
  3. I don’t want to have to map Views to URIs to use the Frame
  4. I need to be able to pass parameters to Views as they are navigated to
  5. I need to support having more than one View implementation in the system for a given View interface type
  6. I need an inspect-able navigation history that I can also configure in terms of how much history to keep and so forth
  7. I would like to support animated transitions from View to View, this is Silverlight after all

My sample application will be an “Audi Fan Site” in Silverlight.

Views & ViewModels

I have a Silverlight “guidance” Solution called HandWaver.AG; I will use some concepts from this solution to build the navigation framework and post the entire solution’s source code. 

Pattern: For separation of concerns, I’ll use the Model-View-ViewModel pattern.

I’ll start with a humble IView base interface:

namespace HandWaver.AG.PresenationModel
{
    public interface IView
    {
        string Title { get; }
        void Activate(Action complete);
        void DeActivate(Action complete);
    }
}

Nothing complicated here.  The Activate and Deactivate methods can be called to inform a IView that it is about to be “started” or shut down.  The Action callbacks will facilitate animation later.

Now I need a ViewModel base class that does a little bit of change notification work for me.

namespace HandWaver.AG.PresenationModel
{
    public abstract class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
    }
}

I will expand on these concepts in a little bit, for now assume that I will have Controls of some kind that implement IView and bind to ViewModels.

Navigation

For the most simple case, I want to be able to just go to an IVIew.  I’ve created an INavigationService interface.  This is the calling convention that I’ll use.

namespace HandWaver.AG.PresenationModel.Navigation
{
    public interface INavigationService
    {
        /// 
        /// Display the first IView implementation we find
        /// 
        /// 
        void NavigateTo< T >() where T:IView;

At this point I can go ahead and create my sample application and my “Home” screen.  I’m going to re-use the Frame and Page concepts from Silverlight.  I have some navigation buttons that are disabled, a ComboBox that will contain my navigation history, and some HyperlinkButtons up at the top to link to the various IViews I will create.

navapp0

The grey area is my navigation Frame.  What I want to do now is Navigate to the Home screen when the app is loaded.  As you can see from the INavigationService code above, I’m just going to do this:

Navigation.NavigateToIHomeView>();

Adding this now displays my Home screen in the navigation frame…

navapp1

… but how did we get there?  The first item is the discovery of IViews.

Discovering Views

In order to meet my design goals, I need to figure out how to find IView implementations automatically without having to create some kind of View Registry.  In my implementation of the INavigationService interface, reflection is the key.  It’s worth going over this code as everything else depends on it:

private void MapViewTypes()
{
    _viewMap = new Dictionary<Type, List<Type>>();
    //Note: we're making a giant assumption here that all Views are in this assembly.  MEF could help?
    
    var types = _viewAssembly.GetTypes();
    var viewType = typeof(IView);
    var pageType = typeof(Page);

    foreach (var t in types)
    {
        if (t.ImplmentsInterface(viewType) && t.IsSubclassOf(pageType))
        {
            var viewImplType = t;
            //if we have a sub-class of IView, use that instead
            var subViewType = (from v in viewImplType.GetInterfaces() where v.InterfaceExtends(viewType) select v).FirstOrDefault();
            if (null != subViewType)
            {
                EnsureList(subViewType);
                _viewMap[subViewType].Add(t);                        
            }
            else
            {
                continue;
            }

        }
    }
}

ImplementsInterface and InterfaceExtends are extension methods I wrote for System.Type.  When this class is created, I’m reflecting the implementing assembly and finding all classes that implement a descended of IView and storing them in a List.  The implementation for the most basic NavigateTo(), then, just looks like this:

public void NavigateTo() where T : IView
{
    var viewType = _viewMap[typeof(T)][0];
    var view = (IView)Activator.CreateInstance(viewType);

    InitializeView(view);
}

In the most basic case, I am just using the first IView type that I find.  As for how the navigation actually happens, I will have to expose a few more implementation details now.

namespace HandWaver.AG.PresenationModel.Navigation.Modules
{
    [Export(typeof(INavigationService))]
    public class URIFrameNavigationService : INavigationService
    {
        public URIFrameNavigationService(string rootNamespace, Assembly va)
        {
            _viewAssembly = va;
            MapViewTypes();
        }

        static Action nullCallback = () => { };

        [Import(AllowRecomposition=true)]
        public Frame TargetFrame { get; set; }

Note that, for now, I am using MEF as an IoC container.  URIFrameNavigationService uses the Export attribute to tell MEF that it implments the INavigationService contract.  When I construct the instance I pass in some basic information and the class uses MEF to import an instance of the Frame class from Silverlight navigation.  So for the most basic kind of navigation, I’m instantiating a new instance of a Page implementing an IView interface and directly setting the Content of the Frame rather than giving it a URI.

Transitions

Next, I’m going to build the “Models” screen of my Audi fan application; in this case we’re talking about Audi cars and not the usual “Model”.  We can go ahead and look at the implementation for InitializeView() now:

void InitializeView(IView v)
{
    Action go = () => 
    {
        TargetFrame.Content = v;
        v.Activate(URIFrameNavigationService.nullCallback);
        History.Navigated(v);
    };

    if (null != TargetFrame.Content && TargetFrame.Content is IView)
    {
        ((IView)TargetFrame.Content).DeActivate(go);
    }
    else
    {
        go();
    }
}

If the Frame is currently displaying an IView, call it’s deactivate method.  When that method is done, the go action is called which activates the new IView.  We also do something with a History object here which I’ll get to in a little bit.  By using callbacks with Activate and Deactivate we’re able to incorporate animations into the navigation mix.  Here is the Activate implementation for Models.xaml:

public void Activate(Action complete)
{
    var trans = (Storyboard)App.Current.Resources["ExpandIn"];
    trans.Stop();
    Storyboard.SetTarget(trans, LayoutRoot);
    trans.Begin();
    EventHandler sbDone = null;
    sbDone = (o, e) =>
    {
        complete();
        trans.Completed -= sbDone;
    };
    trans.Completed += sbDone;
}

I pull a common animation out of resources and call the giving Action when the animation is complete, being sure to unhook event handlers.  In my case, I’d like to use the same Enter and Exit transitions everywhere in the application and I don’t want to keep copy & pasting this code.  I can move this code to a helper class and invoke it this way everywhere else:

public void Activate(Action complete)
{
    Transition.Animate("ExpandIn", LayoutRoot, complete);
}

public void DeActivate(Action complete)
{
    Transition.Animate("ShrinkOut", LayoutRoot, complete);
}

We could, in future refactoring, create some kind of IViewTransitionManager module that automatically does transitions everywhere, and save the Activate and Deactivate methods for other application specific uses.

You can now run the sample application (link at the end of the article) to see the transitions working from the Home screen to the Models screen.

navapp2

 

Passing Parameters

The View Details Hyperlink buttons, above, should navigate to a special screen showing even more  information about the chosen vehicle model.  When this screen loads, then, the chosen Model will need to be available.  We could set some global User State variable specifying what model of Audi was chosen but it would be nicer to navigate to the chosen IView and directly pass parameters to it.  What’s more, it would be ideal if this parameter passing could be strongly typed such that we can determine the types of parameters using Intellisense.

We have already seen how the INavigationService implementation locates and instantiates an IView implementation.  Adding another overload the the interface implementation meets all stated design goals.

/// <summary>
/// Navigate to a View, passing parameters to said view using the supplied Action
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="paramSetter"></param>
void NavigateTo<T>(Action<T> paramSetter) where T : IView;

It may not be apparent at first look what this allows us to do, but consider the current example of choosing a vehicle model from a list.  The ViewModel of the screen we are coming from knows what the selected VehicleModel is.  Using the excellent Generics implementation in C# we can navigate to an IView and easily see what parameters we might be able to pass to it via Intellisense.

protected void ViewDetailsClick(object s, RoutedEventArgs e)
{
    VehicleModel mdl = null;
    var lnk = (HyperlinkButton)s;
    mdl = (VehicleModel)lnk.Tag;
    Navigation.NavigateTo< IModelDetailView>((v) => v.TargetModel = mdl);
}

I am cheating a little bit here, at least it feels like cheating.  My list of vehicle models is implemented as a listbox and I am using (abusing?) the Tag property that Controls expose in Silverlight:

<HyperlinkButton Grid.Column="5" Style="{StaticResource MenuLinkStyle}" Content="View Details" VerticalAlignment="Center" Click="ViewDetailsClick" Tag="{Binding}">                                        
</< span>HyperlinkButton>

Since we can use Bindings for Tag, the actual data type for  each VehicleModel is stored with the Hyperlinkbutton and we can pull it in the Click event handler.  The real power of what we are now able to do is demonstrated when we see the intellisense available when navigating to IModelDetailView and exploring the overloads available:

navapp4

navapp3

Since we have a strongly-typed mechanism, we can create a lambda expression that takes the IView instance and we can inspect the list of public properties available on IModelDetailView.  In my opinion this makes for a perfectly discoverable mechanism for passing parameters directly to an IView.  If you need further help, you could create a class something like RequiredViewParameter;  having such a type in the Intellisene dropdown might help clients determine which properties must be set in order for a View to function.  Obviously, we an set as many properties as we want using the lambda expression.

 

Choosing Between Multiple IView Implementations

Often, there may be only one implementation for a given IView interface at run time and compile time.  For example, there may likely be only a RealFooView (the real production visual) and a MockFooView (used only for unit testing related logic) for a given IFooView interface.  In some cases, though, multiple implementations for a given IView interface may be present in the real run-time system.  For example, there may be “basic” and “expert” views of the same data and these views my be different enough that it doesn’t make sense to use DataTemplates and configuration properties to set up the View.  We’ve already seen that we are keeping a list of IView in the INavigationService, we can now add another overload to this interface to elegantly handle situations where more than one IView implementation is available.

You may have noticed in the various screenshots that there is a CheckBox on the UI with accompanying text “I am a Fanboy”.  The goal here is that if users check this item, we will show them a more rich set of data when they choose View Details.  By passing a sort of Predicate to the INavigationService, we can easily accomplish this goal:

navapp5

For now, the Fanboy checkbox sets a global variable we can access from within Models.xaml.cs.  I’ll use this value from within this Navigate code to create a selector function.

protected void ViewDetailsClick(object s, RoutedEventArgs e)
{
    bool isUserFanboy = App.UserIsFanboy;
    VehicleModel mdl = null;
    var lnk = (HyperlinkButton)s;
    mdl = (VehicleModel)lnk.Tag;
    Navigation.NavigateTo<IModelDetailView>((v) => v.TargetModel = mdl,
        (v) => v.IsFanboyView == isUserFanboy);
}

I can now create two implementations of IModelDetailView, a basic page and the “fanboy” page displaying more detailed information.  Based on this CheckBox option, Navigation will send the user to a completely different IView.

Regular View:

navapp6

Fanboy View, with extra data:

 navapp7

In this case, the Fanboy view could probably have been done without an extra view implementation, but you can likely see how this would be extremely useful.

What Explodes?

As more than one friend has pointed out to me, when building classes to fit into a framework mechanism there can often be an Explosion of classes, enums, interfaces, delegates etc.  What explodes under this approach, or under MVVM in general?

For every Screen in your application you could potentially have a new IView interface, a new ViewModel, and possibly a new Presenter or Commands.

Preventing View Explosion

If a particular View does not need extra methods, you can prevent View explosion by using Generics.  Generics are the answer to everything.  If your View needs a ViewModel and nothing else special, use something like this:

public interface IView : IView where T : ViewModel
{
    T ViewModel { get; set; }
}

This allows you to implement Views, gain the navigation benefits, but not create a new IView interface.

namespace HandWaver.AG.NavDemo.Screens
{
    public partial class SampleView : Page, IView<MainViewModel>
    {

 

Preventing ViewModel Explosion

Given the previous example, you may be worried about your ViewModel classes exploding, one per IView interface.  I may have mentioned before that generics are the answer to everything, sometimes lambda expressions are part of the answer but the answer definitely always involves generics.  You might, for example, need a ViewModel that does nothing but encapsulate an already existing Data Type from your domain.  There’s a generic type for that:

/// 
/// If the ViewModel can be satisfied by a pre-existing data type, 
/// just use that
/// 
/// 
public class ViewModel : ViewModel where T : INotifyPropertyChanged 
{
    public ViewModel(T source)
    {
        Payload = source;
    }

    private T _Payload;

    public T Payload
    {
        get { return _Payload; }
        set
        {
            _Payload = value;
            OnPropertyChanged("Payload");
        }
    }
}

Combined with the previous example, you could get away without another IView or ViewModel implementation:

public partial class SampleView : Page, IView< ViewModel<VehicleModel> >

If VehicleModel satisfies all of your needs for a View, you don’t need to create any new classes or interfaces.

I’ll talk about Presenters and Commands in a future article.

Conclusion

While the current trends in MVVM may downplay the role of a View interface, IView can be a powerful part of your programming toolbox.  Since the View is an actor in this pattern, it makes sense to be able to treat Views a certain way.  In this article you’ve seen how you can build a flexible Navigation framework around Views and even support handy features like strongly typed parameter passing and selecting from multiple implementations when present.  You can do all this without manually creating any kind of mapping.

HandWaver.AG: I mentioned elsewhere I would be publishing the source for all of my Silverlight Guidance demos.  You can find it here, though it may be updated by future articles and look slightly differently than what you read here.

You can also run the Demo Application.

Future Tasks

There are a few things I had to leave out as this article was getting too long.  The first is the promised Navigation History module.  This is 99.9% done but must have its own article. 

Second, and not very relevant here, is the Photo Gallery page.  This will serve up a cool demo when I get to it.

Finally, If you read the source code closely you may have noticed my comments about the reflection-based IView discovery mechanism.   The mechanism makes the assumption that all IViews you can navigate to are in the initial startup assembly.  In most applications that might be a safe assumption, but MEF is working on changing that with dynamic XAP loading.  Once I’ve had a chance to cozy up with MEF more I’ll post an updated solution.  Also related to MEF, storing the composition catalog on the App class is probably not a best practice.



Wednesday, September 16, 2009 7:28:20 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Monday, September 07, 2009

It is sometimes useful or necessary to represent complex data types as name/value pairs, or Dictionaries if you like.  While the Data Binding implementation in Silverlight 3 is admirable, there is not a built in way to do this cleanly.  Doing some Internet searches, you may find some approaches like this, from http://silverlight.net/forums/t/51864.aspx :

public class DictionaryItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var dict = value as Dictionary<string, string>;
        if (dict != null)
        {
            return dict[parameter as string];
        }
        throw new NotImplementedException();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Note that in all cases you will find the “ConvertBack” strategy missing.  Since the original source object is not passed to ConvertBack, two-way binding to  name/value pairs is an elusive goal.  The binding mechanisms in Silverlight 3 are not very extensible.  I cannot create my own binding type or provide a new implementation for Property Paths.  The Silverlight 3 Data Binding framework wants real Properties to bind to.  If we must have two way bindings to name/value pairs, we are left with pursuing more extreme measures.

Dynamic Type Generation

I have written in the past about the complete Reflection Emit implementation in Silverlight.  It seemed to me that given a means of representing the names and types of the items we want to pull out of a dictionary as Properties, we could dynamically generate a bindable version of a class represented as a dictionary.  We’ll start with creating a very simple model for Objects with data represented as name/value pairs.

namespace HandWaver.AG.EVModel
{
    public class Attribute
    {
        public Attribute(int id, string name, Type t)
        {
            Id = id;
            Name = name;
            AttributeValueType = t;
        }

        public int Id { get; set; }

        public string Name { get; set; }

        public Type AttributeValueType { get; set; }
    }
}

This attribute, not to be confused with the .NET Attribute, represents a sort of metadata for a single property on an object.  We give it a name (which ultimately must be friendly to becoming a Property name) and a run time type.  A single Attribute might be the "Name” property of some object with a type of string.  We may not ultimately want to bind to every single name/value pair available to us.  A means of representing a certain sub-Model is therefore very helpful.  A List of Attribute will suffice for this demo.

namespace HandWaver.AG.EVModel
{
    public class AttributeViewModel : System.Collections.Generic.List<Attribute>
    {
        public AttributeViewModel() : this( Guid.NewGuid() )
        {

        }

        public AttributeViewModel(Guid g)
        {
            UniqueId = g;
        }

        public Guid UniqueId { get; set; }
    }
}

The AttributeViewModel class exposes a UniqueId property of type Guid, which will be useful later.

Reflection Emit code, while incredibly powerful, can also be tedious, difficult, and error prone.  Once practice that I follow is to have as little dynamic code as possible, calling out to pre built classes and only doing what must be done in dynamically created types.  In order to be friendly to binding and provide a base to extend we’ll use a base class that does most of what we want to do already:

namespace HandWaver.AG.EVModel
{
    public class EntityWithAttributes : INotifyPropertyChanged
    {
        public EntityWithAttributes()
        {
            _values = new Dictionary<string, object>();
        }

        Dictionary<string, object> _values;

        public object this[string key]
        {
            get
            {
                return _values[key];
            }
            set
            {
                _values[key] = value;
                OnPropertyChanged(key);
            }
        }


        protected void OnPropertyChanged(string propName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

Next, we’ll build a class to create the dynamic types.  I’m currently calling this a Bindable Entity-Value Builder.  It’s worth going over the Reflection Emit code in some detail.  The public interface for BindableEVBuilder is a single method:

public static Type GetDecoratorType(AttributeViewModel prototype)
{
    EnsureDynamicAssembly();
    EnsureModelTypes();
    if (!_modelTypes.ContainsKey(prototype.UniqueId))
    {
        BuildDecoratorType(prototype);
    }

    return _modelTypes[prototype.UniqueId];        
}

We can look at the first several methods later.  The bulk of our work is done in BuildDecoratorType.

static void BuildDecoratorType(AttributeViewModel prototype)
{
    var typeBuilder = _moduleBuilder.DefineType("HandWaver.AG.EVModel.TypeDecorator.DictWrapper"+ GetName(prototype.UniqueId),
        TypeAttributes.Public | TypeAttributes.Serializable | TypeAttributes.Class, 
        typeof(EntityWithAttributes));

    foreach (var attribute in prototype)
    {
        BuildProperty(typeBuilder, attribute);
    }
    _modelTypes.Add(prototype.UniqueId, typeBuilder.CreateType());
}

So far there’s nothing clever here, just creating a dynamic class that extends EntityWithAttributes and making sure that we only generate one dynamic type for each AttributeViewModel by coming up with a naming scheme.  Properties are somewhat special in the .NET CLR.  In order to create a property using IL, the property itself must be defined as well as a getter and setter method.

static void BuildProperty(TypeBuilder typeBuilder, Attribute attr)
{
    var baseType = typeof(EntityWithAttributes);
    var propertyBuilder =
        typeBuilder.DefineProperty(attr.Name, PropertyAttributes.None, attr.AttributeValueType, null);
    // The property set and property get methods require a special
    // set of attributes.
    MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

    var getterBuilder = BuildGetter(typeBuilder, attr, baseType, getSetAttr);

    var setterBuilder = BuildSetter(typeBuilder, attr, baseType, getSetAttr);

    propertyBuilder.SetGetMethod(getterBuilder);
    propertyBuilder.SetSetMethod(setterBuilder);
}

The getter is more interesting than the setter in this situation.

private static MethodBuilder BuildGetter(TypeBuilder typeBuilder, Attribute attr, Type baseType, MethodAttributes getSetAttr)
{
    var getterBuilder = typeBuilder.DefineMethod("get_" + attr.Name, getSetAttr, attr.AttributeValueType, Type.EmptyTypes);
    var getterILGen = getterBuilder.GetILGenerator();

    var baseGetterInfo = baseType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
        null, new Type[] { typeof(string) }, null);

    LocalBuilder localValBuilder = getterILGen.DeclareLocal(attr.AttributeValueType);
    // Preparing labels
    Label label20 = getterILGen.DefineLabel();
    // Writing body
    getterILGen.Emit(OpCodes.Nop);
    getterILGen.Emit(OpCodes.Ldarg_0);
    getterILGen.Emit(OpCodes.Ldstr, attr.Name);
    getterILGen.Emit(OpCodes.Call, baseGetterInfo);
    if (attr.AttributeValueType.IsValueType)
    {
        getterILGen.Emit(OpCodes.Unbox_Any, attr.AttributeValueType);
    }
    else
    {
        getterILGen.Emit(OpCodes.Castclass, attr.AttributeValueType);
    }
    getterILGen.Emit(OpCodes.Stloc_0);
    getterILGen.Emit(OpCodes.Br_S, label20);
    getterILGen.MarkLabel(label20);
    getterILGen.Emit(OpCodes.Ldloc_0);
    getterILGen.Emit(OpCodes.Ret);
    return getterBuilder;
}

It is a convention that property methods are named as get_ and set_ plus the actual public property name.  What’s interesting here is the code we must generate to call the dictionary methods on the base class.  You will note that the method name is “get_Item”, which I only discovered by using Reflector.  I made the decision that I wanted I wanted the generated Properties to be strongly typed rather than return Object.  After emitting the OpCodes for calling the base class’s dictionary get method, we cast the Object to the type specified by the Attribute used to build this Property.  When I was first testing this I had properties of type string and double; the string was working and the double was not.  The Castclass opcode produces odd results when working with value types, so I found the correct Opcode for non-reference types which is naturally OpCodes.Unbox.

If you want to become more familiar with what the CLR is really doing, try writing Reflection Emit versions of some common tasks.

The setter code is straightforward as far as these things go.

private static MethodBuilder BuildSetter(TypeBuilder typeBuilder, Attribute attr, Type baseType, MethodAttributes getSetAttr)
{
    var setterBuilder = typeBuilder.DefineMethod("set_" + attr.Name, getSetAttr, null, new Type[] { attr.AttributeValueType });
    var setterILGen = setterBuilder.GetILGenerator();
    var baseSetterInfo = baseType.GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(string), typeof(object) }, null);
    setterBuilder.SetReturnType(typeof(void));
    setterBuilder.SetParameters(attr.AttributeValueType);
    // Parameter name=value
    ParameterBuilder value = setterBuilder.DefineParameter(1, ParameterAttributes.None, "value");
    ILGenerator gen = setterBuilder.GetILGenerator();
    // Writing body
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ldarg_0);
    gen.Emit(OpCodes.Ldstr, attr.Name);
    gen.Emit(OpCodes.Ldarg_1);
    gen.Emit(OpCodes.Call, baseSetterInfo);
    gen.Emit(OpCodes.Nop);
    gen.Emit(OpCodes.Ret);
    return setterBuilder;
}

 

Proving it Out

With a first draft of the reflection code written, I wanted to write a simple UI to smoke test three obvious Data Binding scenarios:

  1. Basic binding to a dynamically generated property
  2. Invoking code manually to update a property to make sure update notifications are firing
  3. Change a value using a Control of some kind to make sure TwoWay binding is updating the instance 

These goals can be met with a simple and unglamorous user interface:

<Grid x:Name="LayoutRoot" Width="450" HorizontalAlignment="Left">
      <StackPanel>
          <TextBlock FontSize="30" FontFamily="Verdana">Things that I have time for:</TextBlock>
          <TextBlock Text="{Binding Code}"></TextBlock>
          <TextBox Text="{Binding Wine, Mode=TwoWay}"></TextBox>
          <Border CornerRadius="5" BorderBrush="Red" BorderThickness="2">
              <Border.Child>
                  <TextBlock Text="{Binding Wine}"></TextBlock>
              </Border.Child>
          </Border>
          <Button x:Name="ChangeBtn" Click="ChangeBtn_Click" Content="Change"></Button>
          <StackPanel Orientation="Horizontal">
              <TextBlock>Money(double)</TextBlock>
              <TextBlock Text="{Binding Money}"></TextBlock>
          </StackPanel>
      </StackPanel>
</Grid>

Yes, I’ve identified Code, Wine, and Money (and little else) as things that I have time for.  You’ve got to write what you know.  In the Loaded event handler for this basic Control, we can see the Entity Value classes in action.  The first step is to create a simple model to generate a bindable Type from.

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    var model = new AttributeViewModel();
    model.Add(new HandWaver.AG.EVModel.Attribute(0, "Wine", typeof(string)));
    model.Add(new HandWaver.AG.EVModel.Attribute(1, "Code", typeof(string)));
    model.Add(new HandWaver.AG.EVModel.Attribute(2, "Money", typeof(double)));

First we’ll try one object with three attributes.  Creating an instance of the dynamic type looks like this:

var t = BindableEVBuilder.GetDecoratorType(model); _entity = (EntityWithAttributes)Activator.CreateInstance(t);

var t =  BindableEVBuilder.GetDecoratorType(model);
_entity = (EntityWithAttributes)Activator.CreateInstance(t);
_entity["Wine"] = "Chateauneuf du Pape";
_entity["Code"] = "Silverlight";
_entity["Money"] = 5555785.0;
LayoutRoot.DataContext = _entity;

Time for the moment of truth.  Running the code and interacting with the UI yields the following:

UI0

Everything works.  The one time binding “Silverlight” works, I typed Malbec in the TextBox and it updated the object, the Property changed evens fired, and clicking the Change button changed the bottom text to 1000000.  My dynamic property system works.

Going a Little Further

The basic binding situations work, but what about a slightly more complex scenario?  Let’s go ahead and test multiple dynamic types, multiple instances, and IValueConverters.

void BindGrid()
{
    var carModel = new AttributeViewModel();
    var year = new HandWaver.AG.EVModel.Attribute(0, "Year", typeof(int));
    var make = new HandWaver.AG.EVModel.Attribute(1, "Make", typeof(string));
    var model = new HandWaver.AG.EVModel.Attribute(2, "Model", typeof(string));
    var series = new HandWaver.AG.EVModel.Attribute(3, "Series", typeof(string));
    var msrp = new HandWaver.AG.EVModel.Attribute(4, "MSRP", typeof(double));
    carModel.AddRange( new List<HandWaver.AG.EVModel.Attribute>() {year,make,model,series, msrp} );

    var carType = BindableEVBuilder.GetDecoratorType(carModel);

    var wrx = (EntityWithAttributes)Activator.CreateInstance(carType);
    var s4 = (EntityWithAttributes)Activator.CreateInstance(carType);
    var s4Prestige = (EntityWithAttributes)Activator.CreateInstance(carType);

    year.SetValue(wrx, 2002);
    make.SetValue(wrx, "Subaru");
    model.SetValue(wrx, "Impreza");
    series.SetValue(wrx, "WRX");
    msrp.SetValue(wrx, 26000.00);

    year.SetValue(s4, 2010);
    make.SetValue(s4, "Audi");
    model.SetValue(s4, "S4");
    series.SetValue(s4, "Premium Plus");
    msrp.SetValue(s4, 47900.00);

    year.SetValue(s4Prestige, 2010);
    make.SetValue(s4Prestige, "Audi");
    model.SetValue(s4Prestige, "S4");
    series.SetValue(s4Prestige, "Prestige");
    msrp.SetValue(s4Prestige, 53000.00);

    var carList = new List<EntityWithAttributes>() {wrx, s4, s4Prestige};
    CarGrid.ItemsSource = carList;
}

You can see that there’s a bit of code being written to create the instances and set the values, but we could obviously write more code around that to automate more of the tedious work.  I will also note that AutoGenerateColumns=”True” did not work on the DataGrid: I leave that as an exercise for another day.  The resulting display is exactly what you’d expect:

UI1

 

A little polish

When first testing this code, I could see that it worked but inspecting the dynamically generated EntityWithAttributes descendant was producing odd results in the Visual Studio debugger.  Even trying to add a watch for the base class would show an error like “Unable to evaluate expression”.  Silly rabbit, I had forgotten to include debug information in my Reflection Emit code.  This turned out to be a lot easier than it sounds.  Let’s take a look at the EnsureDynamicAssembly method that I skipped earlier.

        /// <summary>
        /// Debugger info found at http://blogs.msdn.com/jmstall/archive/2005/02/03/366429.aspx
        /// </summary>
        static void EnsureDynamicAssembly()
        {
            if (null == _dynamicName)
            {
                var appDomain = AppDomain.CurrentDomain;
                _dynamicName = new AssemblyName("HandWaver.AG.EVModel.TypeDecorator");

                _aBuilder = appDomain.DefineDynamicAssembly(_dynamicName, AssemblyBuilderAccess.Run);
#if DEBUG
                var debugAttrType = typeof(DebuggableAttribute);
                var debugAttrCtor = debugAttrType.GetConstructor(new Type[] { typeof(DebuggableAttribute.DebuggingModes) });

                var customAttributeBuilder =
                    new CustomAttributeBuilder(debugAttrCtor,
                        new object[] { DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default });
                _aBuilder.SetCustomAttribute(customAttributeBuilder);
#endif
#if DEBUG
                _moduleBuilder = _aBuilder.DefineDynamicModule(_dynamicName + ".dll", true);
#else
                _moduleBuilder = _aBuilder.DefineDynamicModule(_dynamicName + ".dll");
#endif
            }
        }

I don’t usually use preprocessor directives but this is exactly what they’re for.  The stuff in between the #if DEBUG statements includes some symbol information in the dynamic assembly.  There’s more work I could have done to associate the code to a Document for source step-through, but at least going this far gets my Local/Watch windows in VS working:

WatchWindow

You can see that I can evaluate properties on the base class and even Reflect the dynamic type to see that it exposes “real” properties like any other Type.

Conclusion

There is a saying that every problem in computer science can be solved with one more level of indirection.  When using the Full .NET Framework it often seems they’ve thought of everything, even providing an effective layer of indirection for Reflection in the form of TypeDescriptor and friends.  Lacking TypeDescriptor in Silverlight, it’s up to us in the community to come up with solutions while we simultaneously pester Microsoft to add more extensibility to the Data Binding frameworks.



Monday, September 07, 2009 12:59:55 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Saturday, August 15, 2009

I have been happily using the Unity container for over a year now.  I had previously written my own IoC framework in Silverlight and used some other off the shelf and custom home-grown containers.  I have recently been getting started using MEF in Silverlight as part of some up and coming Patterns articles.

When you scratch the surface of MEF, I’ll warn you that you may be Underwhelmed.  What, exactly, is this?  The Ultimate IoC container?  What is this doing for me that Unity wasn’t already doing for me?  In fact, you can implement the IUnityContainer interface with MEF so what’s the big deal?

Is the big deal…

  • That MEF is the Visual Studio 2010 extensibility mechanism?  No. Microsoft has claimed that they needed MEF for internal efforts like this.  I believe they are earnest, that this is not just a public “Look at us eating our own dogfood” showing.  Still, Microsoft needed the Entity Relation model beneath the Entity Framework and we saw how well that was received by the community.
  • That MEF works in Silverlight?  No.  Other IoC containers were ported to Silverlight 2 long before Unity or MEF.  We’ve been able to use the same container for Silverlight/WPF/ASP.net/Winforms/Console apps for a long time.
  • That MEF has cool features like Catalogues, Dynamic Recomposition, Lazy<T> ? No.  These features are cool and I plan on exploring them further and talking about them to anyone who will listen.

No, the big deal is that MEF is shipping with .NET 4.

So what, you say? Let me explain.  A lot of you probably listen to .NET Rocks.  I do, I enjoy it.  The hosts are funny, the guests are bright, and I get bite-sized updates on what is going on out there in areas of the development universe that are important to me but not so important as to be in my overloaded RSS list.  .NET rocks succeeds for various reasons and to hone in on one of the big whys let’s take a look at one possible way to group developers:

  1. Brand new developers. 
  2. Developers who are lazy clock-punchers who don’t care about their craft whatsoever.  Enough said about these folks.
  3. Developers who know enough to know there are better ways.  They struggle within the bureaucracy.  They’ve heard testing is good, but why?  They feel they probably need abstractions, but where?  Some don’t quite have the motivation or the skills the find the answers themselves; some have never been afforded the opportunity to break out.
  4. Developers who think they have all of the answers but are full of $(‘.crap’).
  5. Developers who mostly “get it”, who have the motivation and skills to find the answers, refine their craft, and make things better.

Based on my own experience Group #3 makes up an awful large percentage of the developer world.  A lot of the folks in Group #5 start here until something snaps within them and they decide to stop playing WoW and get serious about figuring out what it takes to get better.   These #3 folks want to learn but the lure of American Idol keeps them from catching up on those blogs.  They want to try a new pattern but the Architecture Police have decreed that they must never do X and always do Z.  Maybe the political war required to get a new library into the solution to try a different way kills any initiative.  Maybe their employer never springs for training.  More often than not, the high turnover in IT isolates developers from the long term perspective that would otherwise be a great teacher.  Which abstractions worked and which turned out to be nightmares or at best simply unnecessary?  Who knows.  We don’t go back and ask because we’re afraid of the answers, and to be fair we all hate each others’ code anyway.

The .NET rocks show and things like it is a little beacon of light, a reminder that some people are really doing things right out there, and staying on the cutting edge, and delivering a lot of value.   But, Damon, how does this relate back to MEF?  Because Group #3 is looking for guidance.  How many guests have debated which Data Access technology Microsoft “wants us to use” ?  Do they want me to use LINQ to SQL or Entity Framework?  Yes, the good folks behind door #3 who are in the .NET space overwhelming look to Microsoft for that guidance.  When Microsoft showed creating SQL DataAdapters inside button click event handlers that’s what they did.  When Microsoft said Stored Procedures are the way that’s what they built.  When Microsoft said SOA was good we learned SOAP.  When Microsoft endorsed jQuery we learned jQuery. 

By putting MEF in the .NET framework the community of well-meaning folks who want to do better are going to see a new message, some new guidance.  “Microsoft wants me to think of my applications differently.”  Microsoft is telling me that my apps should be composed out of modules, perhaps modules hidden behind interfaces.  I should worry about the physical location of a module or its implementation later and program against abstractions.  When I write a class I should think about what the responsibility of this class is and what its dependencies are.  Microsoft is telling me to get onboard with loose coupling.  I don’t need to petition my overlords to bring in a new framework because the only thing between me and MEF is:

using System.ComponentModel.Composition;

Microsoft has always been a Platform company.  I like my Zune, the Xbox is cool, I’m a PC, and maybe the Microsoft Stores will be cool.  But let’s be real: what Microsoft does better than anything else is to build something that other people use to build something.  By including MEF in the core toolbox Microsoft is getting behind a lot of solid development ideas and removing another barrier between the Average Corporate Developer and Better.

 



Saturday, August 15, 2009 7:30:59 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Monday, August 03, 2009

This weekend I was trained in the ancient art of Sabrage for Champagne (or sparkline wine).  Rather than the pedestrian practice of removing the cage and pushing on the cork with your thumbs, you chop the top off of the bottle with a champagne saber or chef’s knife.  Here’s my first successful cut:

ChampagneSaberage

 

There is, as you may suspect, a trick to it.  I was taught the ancient secrets by sensei Phil at Thief Wine.  As if my love for Champagne wasn’t already great enough, now I also have an amazing party trick to go with it.



Monday, August 03, 2009 5:38:56 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  |  Trackback

I have just switch DamonPayne.com over to some better iron.  If you’re seeing this, all is well!



Monday, August 03, 2009 5:33:20 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, July 14, 2009

One natural way to create some visual effects would seem to be animating the clipping path of a visual element.  Sitting down in either Visual Studio or Blend 3 will immediately show there’s not a straightforward way to do this.  There have been some other means of doing this posted online involving  creating a Storyboard and DoubleAnimation entirely in a code-behind.  Since one of our goals when using Silverlight and Blend should be a clean designer/developer separation,  I didn’t care for this approach. 

We’re going to build a “wipe” effect using animation and clipping paths and the only code behind will be the Storyboard trigger.

Setup

I’m first going to create a Silverlight 3 Navigation application and throw in my own styles.  I add a Page called AnimateClip.xaml and throw in a DataGrid containing some sample wine data and a button I can push to test the “wipe” effect.  The application looks like this when I navigate to the new page:

ss0

 

DataGrid XAML

I’m going to apply the Wipe effect to the DataGrid.  Here’s the initial XAML defining my grid.  As you’ve already seen above I created some Sample Wine data to populate the DataGrid.

<data:DataGrid x:Name="WineGrid" AutoGenerateColumns="True" IsReadOnly="True" CanUserResizeColumns="True" Grid.Row="1" Width="500" Height="200" RenderTransformOrigin="0,.5">
    <data:DataGrid.Clip>
        <RectangleGeometry Rect="0,0,500,200">
            <RectangleGeometry.Transform>
                <ScaleTransform x:Name="WipeScale" ScaleX="1" ScaleY="1"/>
            </RectangleGeometry.Transform>
        </RectangleGeometry>
    </data:DataGrid.Clip>
</data:DataGrid>

Note that I’ve given the DataGrid a clipping geometry that exactly matches the bounds the DataGrid has anyway.  The RectangleGeometry gets its dimensions from a Rect property.  The struct Rect has a Width property, but Rect.Width does not appear to be backed by a DependecyProperty, so we can’t simply animate the Width of a Rect.  Without creating new Rect structs and manually animating in C#, some trial and error was needed in order to find a workable XAML-only solution.  The solution is to name the ScaleTransform and animate its Properties.

I’m going to create the Storyboard manually in XAML, we’ll see why when moving to Blend 3 in a minute.

<Storyboard x:Name="WipeGrid">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="WipeScale"
                                   Storyboard.TargetProperty="ScaleX">
        <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
        <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

So, this is fairly simple once we figure out how to effectively animate the bounds of the DataGrid.  Ordinarily this Storyboard would produce a uniform “shrink in” effect.  The default RenderTransformOrigin is of course the very center of a UIElement.  Because the RenderTransformOrigin of the DataGrid is set to 0, .5 we get the desired “wipe” effect as we are calculating from the left side rather than the center.

When I press the Wipe Out button the code-behind starts the Storyboard.  The wipe effect now works as desired.

Polish

As I enjoyed how the wipe effect looked, I thought perhaps I’d use some of the new built in easing functions to make it even better.  In the recently released Expression Blend 3 + SketchFlow, this is what I see when attempting to edit my Storyboard:

ss1

Despite the fact that the Storyboard works,  the clipping path is missing something needed for Blend to be able to show it for timeline editing.  I assume this is because it’s technically not a visual element in the tree, but just a humble RectangleGeometry used to modify a visual element.  I really don’t feel like learning the ins and outs of all of the easing functions and their parameters, so for now I had to create a bogus storyboard and copy it to this Page.  The Quadratic Ease (InOut) produced the effect I was going for.

<Storyboard x:Name="WipeGrid">
    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="WipeScale"
                                   Storyboard.TargetProperty="ScaleX">
        <EasingDoubleKeyFrame KeyTime="00:00:00" Value="1">
            <EasingDoubleKeyFrame.EasingFunction>
                <QuarticEase EasingMode="EaseInOut"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
        <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0">
            <EasingDoubleKeyFrame.EasingFunction>
                <QuarticEase EasingMode="EaseInOut"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

So, while that would not be bad as far as hand-crafting XAML it would be better if I didn’t have to build fake Storyboards to create my visual effects.  With a more complex Storyboard mistakes might be made in the manual copy & conversion process.  You now have an alternate way to animate clipping paths in Silverlight using XAML.



Tuesday, July 14, 2009 7:46:00 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, July 05, 2009

I have just applied to join the recently created INETA Regional Speaker program.  It’s unclear whether or not there is an approval process.  This program is meant for people who “are not ready for the national program”; read: I’m no Scott Hanselman.  This is the “farm team” for the national program.  I have asked them to add Parallel Programming as a topic and I hope to take my Silverlight and PFX show on the road.



Sunday, July 05, 2009 2:06:47 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, July 01, 2009

I am proud to be able to announce today that I have been award the Microsoft MVP award in the proficiency of Smart Client technologies. 

I’m extremely appreciative of my nomination and of my new MVP Lead Suzanna Moran.  I’m already excited about the summit next year!  There’s a lot of exciting things coming from MSFT, and I’ve got a lot of community involvement planned for the coming year.



Wednesday, July 01, 2009 11:11:28 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback