Speaking at Chippewa Valley Code Camp 2009

by Administrator 6. November 2009 04:18

In just over a week, on November 14th, I will be speaking at the Chippewa Valley Code Camp taking place way up in Menomonie, WI on the UW-Stout campus.  The topic is Advanced Silverlight Development however the content will be somewhat different than my talk by the same name I gave at MadCamp a little while ago.  Doug and company run a healthy community so I’m looking forward to good conversations.

Details on the code camp can be found at: http://www.chippewavalleycodecamp.com/ 

The schedule of topics can be found here: http://www.chippewavalleycodecamp.com/Schedule/2009Schedule/tabid/74/Default.aspx

The elusive Christopher J. Barwick will be accompanying me and making his return to Public Nerd Life.  I am looking forward to seeing Jason Bock and Chris speak, and I’ll probably check out some of the non-Microsoft or Building Better Software topics in between.  We’ll be up the night before and open to grabbing a drink with any local geeks or speakers who may be available.

Tags:

New Car

by Administrator 23. October 2009 20:30

In order to increase the prestige of the Microsoft MVP program and the practice of .Net user group presentations, I have purchased a new automobile.

DamonS4

This is my 2010 Audi S4 – there are many like it but this one is mine.  After driving the WRX for almost 9 years I thought I could splurge a little bit. 

Tags:

Silverlight and Mailto:

by Administrator 22. October 2009 04:24

This may be obvious to some, but by calling out to JavaScript within the document hosting your Silverlight application, you can do some powerful things.  Back in the day, we used to sometimes use an href with “mailto” as a poor man’s contact form – hosting solutions with databases and backups weren’t always as cheap and plentiful as they are today.  If you lack a Service Layer to email solution in your environment, you can always try the following:

private void Mailto_Click(object sender, RoutedEventArgs e)
{
    var svc = new Modules.BrowserHostService();
    svc.CallHostFunction("MailTo", "damon@damonpayne.com", "Damon", "Try this Wine!", 
        "Roger Sabon Chateauneuf du Pape 2005", "11F16974-8EE1-4c0c-8AB4-21EF0B7BF087");
}

Where BrowserHostService is part of a demo that I’m working on.  The implementation is very simple:

public class BrowserHostService : IHostService
{
    public void CallHostFunction(string func, params string[] args)
    {
        HtmlPage.Window.CreateInstance(func, args);
    }

This method does everything needed to invoke a JavaScript method on the document containing the Silverlight application.  For invoking the user’s default mail program, you could write a function like what’s shown below.  The only item of note is that the parameter orders must match up.  If you’ve done much Reflection coding you should be used to this.

<script type="text/javascript">
    function MailTo(toEmail, fromUser, subject, suggestTopic, suggestCode) {

        var body = fromUser
        + ' thought you would really enjoy '
        + suggestTopic 
        + ' and there is some info about that on TastingProject.com.   '
        + 'Why not head over to http://localhost:5785/TastingProject.UITestPage.aspx?code='
        + suggestCode 
        + ' and check it out?';

        window.open('mailto:'+ toEmail +'?subject=' + subject+'&body='+body);
    }        
</script>

The preceding C# and JavaScript produces the following result on my machine in Outlook:

AGmailto

Of course you would have to rely on your end user to hit the Send button but this may be a quick and dirty way to get email functionality if you don’t have complete control over your environment.

Tags:

Speaking at MadCamp and 7 Fest

by Administrator 15. October 2009 01:36

On Saturday, October 24th I will be speaking at the Madison .NET User’s Group’s annual Code Camp: MadCamp.  You can find general information about MadCamp here. My presentation will be on Advanced Silverlight Topics.  They are going to be giving away a lot of cool stuff, particularly around Windows 7.  The group has combined the code camp event with a Microsoft sponsored Windows 7 launch party so it should be pretty sweet.  I will be tweeting on the subject using #madcamp09 and I hope to see you there

Tags:

Argentum Tela Design Surface [21] &ndash; Name Provider

by Administrator 5. October 2009 02:08

The AGT (Argentum Tela) series of articles is an effort to do two things. Usually an idea is presented only in its finished form. The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches. The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008. This type of application has all sorts of interesting uses. My example is a Home Theater layout tool. Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

What’s in a name?

If you have worked in the Windows Forms designer, ASP.Net ViewState, ASP.Net Control Templates, or ever used a design surface of any kind you are likely familiar with the concepts of a Naming Container and Name Providers.  The first Label I drag onto a form might get a name of “Label0”, then “Label1” and so on.  Many visual technologies will throw an exception if two items inside the same container have the same name.  We will need this idea for AGT very soon, so now is the time to implement it.

Design Goals

The design goals for this next step are fairly simple:

  1. We must have a notion of A Container.  This container has children, this container will use some sort of Name provider to provide a default name for each new Child added to it.
  2. The Type of the children should be inspect able, such that we can supply names like “Foo0”, etc.
  3. We do not need to support a parent-child relationship between Containers (like asp.net does).
  4. We should let the Caller set the name on its child

The only remaining decisions are small but important. 

  1. Is there any value to having an INamingContainer interface or can we use an existing mechanism to expose children?
  2. Is there any value to having an INameable interface for items to be named?

I’m going with “yes”, and “no”, respectively.

INamingContainer

I’m going to create a simple INamingContainer interface which can be implemented by containers (like a design surface) that want their users to have a unique name.  I could make this part of the IDesigner interface but I’d like this to be optional.  I am still in my IDesignableControl-centric world though.

namespace DamonPayne.AGT.Design
{
    /// <summary>
    /// Represents something that has children needing unique names
    /// </summary>
    public interface INamingContainer
    {
        IList<IDesignableControl> Children{get;}
    }
}

This is all we need, we can now enumerate the children and generate a unique name.

INameProvider

The interface for INameProvider is equally simple.

namespace DamonPayne.AGT.Design.Contracts
{
    public interface INameProvider
    {
        string GetUniqueName(INamingContainer container, IDesignableControl newChild);
    }
}

As I mentioned before, I’d like to follow the familiar convention of ControlType[number], so I’m ready to build a default implementation for INameProvider.  This is pretty easy using LINQ.

namespace DamonPayne.AGT.Design.Services
{
    /// <summary>
    /// A name provider that uses the last part of type name plus 
    /// </summary>
    public class TypeScopedNameProvider : INameProvider
    {
        public string GetUniqueName(INamingContainer container, IDesignableControl newChild)
        {
            var type = newChild.GetType();
            string namePart = type.Name;
            int existingCount = (from c in container.Children where c.GetType() == type select c).Count();
            return namePart + existingCount;
        }
    }
}

 

Hooking up DesignSurface

In order to finish up, I only need to hook my implementation up using Unity and call the name provider whenever a new item is added to the DesignSurface.

[Dependency]
public INameProvider NameProvider { get; set; }

 

private void EnsureName(IDesignableControl dc)
{
    if (string.IsNullOrEmpty(dc.DesignTimeName)) 
    {
        string name = NameProvider.GetUniqueName(this, ((DesignSite)dc).HostedContent);
        dc.DesignTimeName = name;
    }  
}

I can drag things out without a name now, and everything looks the way it should with the generated naming.  My glorious purple couches and poorly drawn speakers have names!  Now that I’ve been learning Expression Design I should really take another crack at drawing those speakers.

21ss0

I’ve really got to fix the way that PropertyGrid looks too.

Conclusion

The Service/Module based approach continues to prove itself out as the correct approach for making it easy to add new functionality to the system.  Adding a name provider was a small feature, but the next step won’t be so easy.

You can get the source code from codeplex.  This article represents change set 28479.

The live demo has been updated and can be viewed here.

Tags:

Argentum Tela Design Surface [20] &ndash; Getting up to speed

by Administrator 25. September 2009 02:00

The AGT (Argentum Tela) series of articles is an effort to do two things. Usually an idea is presented only in its finished form. The first goal is to do some Reality Blogging, to show an idea evolve over time without pulling any punches. The second goal, and the example vehicle for the evolution aspect, is an extensible Design Surface for Silverlight similar to what we have in Visual Studio 2008. This type of application has all sorts of interesting uses. My example is a Home Theater layout tool. Read the entire saga: http://www.damonpayne.com/2008/09/14/RunTimeIsDesignTimeForAGT0.aspx

Atrophy

As of AGT[19] I was getting ready to extend Commanding and introduce some other concepts in order to get Undo/Redo support.  Of course, that was many months ago and I’ve let this sit for a while haven’t I?  Since that time a lot has happened.  Silverlight 3 has shipped, there are many more class libraries available, and Silverlight in general is being taken more seriously.  It’s time to continue working on the design surface project.

Ok, fine, I also need AGT for some other projects.  I need to take some time to bring the project up to the state of the art and change direction slightly to move the road map around to be more in line with my own short term needs.  Let’s get started.

If you’re new to this project, you can also check out the Codeplex site.

Silverlight 3 Upgrade

Since I’ve been through a machine repave or two since my last work I had to get Team System set back up for Codeplex.  I didn’t realize this until after I’d opened the solution and done the conversion wizard so I was concerned.  Sure enough, the project upgrade hozed the source control bindings but I was able to get it fixed using the Change Source Control command.  With this done I built and ran with no problems, however trying to change anything revealed that source control was most likely irrevocably ruined so I got latest and went back to work.

Once I got through all this, the Silverlight 3 upgrade went off without a hitch.  I found exactly zero breaking changes in the application so far; this is much nicer than some of the previous Silverlight 2 cycles I had gone through.

While no changes were strictly necessary, I had to think about taking advantage of new Silverlight 3 features.  I quickly cycled through my mental list of new Silverlight 3 features.  I may use things like Behaviors in the future.  One thing I wasn’t thrilled with from Silverlight 2 was the copy/scale/glass approach I had to take for creating my drag & drop “thumbnails” of controls.  I sat down to see how much work it would take to create an IDragTypeCreator implementation using WritableBitmap.  WriteableBitmap still has some bizarre behavior in some situations so unfortunately I had to stick with the old implementation.

Refactoring

Pretty much any time I look at old code, I’m eager to apply whatever I’ve since learned to it.  AGT is no exception.  In order to get my head back into this codebase I needed to come up with a refactoring goal that would cause me to review everything…

Moving to Unity

Now that Unity for Silverlight is in good shape, there’s no reason for me not to use it.  I have now taken a dependency on Unity 1.2.  It was hard to say goodbye to my own IoC container but it needed to be done.  Were there any issues in this upgrade?  Oh, you might say so…

  1. I removed my IService interface and replaced with Unity [Dependency] attributes.  This of course involved touching nearly every file in the project.  Find an IService interface, find the implementing classes and the importing classes; lather, rinse repeat.  This was super-painful.

  2. I decided to keep my own EventAggregator for now.

  3. I am also keeping my lame Region Manager for now

  4. The old Creative Commons declarations were removed since AGT is really MS-PL now.

While this resulted in a massive change set, it felt good.  This was a very eye-opening experience:

Changing your IoC container might mean touching most of the files in your solution!

Design Surface

Once I got the solution back up and running with Unity and Silverlight 3, I started looking at areas where I could clean up the design.  The DesignSurface implementation is only 300 lines right now, but is also likely to grow in the future.  I decided to use a concept from another article to encapsulate drawing on the design surface.

namespace DamonPayne.AGT.Design.Behaviors.Drawing
{
    public abstract class DrawingBehavior
    {
        public DrawingBehavior(Canvas surface)
        {
            Surface = surface;
        }

        /// <summary>
        /// The surface we're drawing on
        /// </summary>
        public Canvas Surface { get; private set; }

        /// <summary>
        /// Mouse click point relative to Surface    
        /// </summary>    
        public Point StartPoint { get; set; }

        public abstract void StartDrawing(Point s);

        /// <summary>    
        /// Give derrived classes a chance to determine if they can or should return a valid     
        /// Shape in their current state    
        /// </summary>    
        /// <param name="g"></param>    
        /// <returns></returns>    
        public virtual bool ShouldStopDrawing(DrawingGestures g)
        {
            return (g == DrawingGestures.MouseLeftButtonUp);
        }

        /// <summary>    
        /// Stop drawing and return the final Shape    
        /// </summary>    
        /// <returns></returns> 
        public abstract Shape StopDrawing();


        /// <summary>    
        /// Pass Mouse events through to the DrawingBehavior    
        /// </summary>    
        /// <param name="e"></param>    
        public abstract void MouseMove(MouseEventArgs e);
    }

}

If you are a long-time follower of this series or you’ve read the road map on Codeplex, you’ll know that I intend to have an extensible behavior mechanism for making things happen on the design surface.  DrawingBehvior is the first step in that direction, and also allows me to take a lot of code out of the design surface and move it to a dedicated construct.

namespace DamonPayne.AGT.Design.Behaviors.Drawing
{
    public class RectangleDrawingBehavior : DrawingBehavior
    {
        public static readonly double SELECT_RECT_STROKE_WIDTH = 3.0;
        public static readonly double SELECT_RECT_RADIUS_X = 0.0;
        public static readonly double SELECT_RECT_RADIUS_Y = 0.0;

        public RectangleDrawingBehavior(Canvas surface) : base(surface) { }

        public Rectangle DrawingRect { get; set; }

        public override Shape StartDrawing(Point s)
        {
            StartPoint = s; 
            DrawingRect = new Rectangle { Width = 5.0, Height = 5.0, };
            ApplyShapeStyle(DrawingRect);
            DrawingRect.SetValue(Canvas.LeftProperty, s.X);
            DrawingRect.SetValue(Canvas.TopProperty, s.Y);
            Surface.Children.Add(DrawingRect);
            return DrawingRect;
        }

        public override Shape StopDrawing()
        {
            var rVal = DrawingRect;
            DrawingRect = null;
            return rVal;
        }

        public override void MouseMove(MouseEventArgs e)
        {
            Point localMousePos = e.GetPosition(Surface);
            if (StartPoint.X < localMousePos.X)
            {
                double width = localMousePos.X - StartPoint.X;
                double height = localMousePos.Y - StartPoint.Y;
                if (width > 0 && height > 0)
                {
                    DrawingRect.Width = width;
                    DrawingRect.Height = height;
                }
            }        
            else // northwest drag        
            {            
                double width = StartPoint.X - localMousePos.X;
                double height = StartPoint.Y - localMousePos.Y;
                if (width > 0 && height > 0)//need this safety here in case a resize rectangle "crosses" itself.           
                {
                    DrawingRect.Width = width;
                    DrawingRect.Height = height;
                    DrawingRect.SetValue(Canvas.LeftProperty, localMousePos.X);
                    DrawingRect.SetValue(Canvas.TopProperty, localMousePos.Y);   
                }       
            }         
        }

        public virtual void ApplyShapeStyle(Shape s)
        {
            DrawingRect.StrokeThickness = SELECT_RECT_STROKE_WIDTH;
            DrawingRect.RadiusX = SELECT_RECT_RADIUS_X;
            DrawingRect.RadiusY = SELECT_RECT_RADIUS_Y;
            DrawingRect.Stroke = new SolidColorBrush(Color.FromArgb(0xFF, 0x15, 0x05, 0xFF));
            DrawingRect.Fill = new SolidColorBrush(Color.FromArgb(0xFF, 0x49, 0x59, 0xFF));
            DrawingRect.Opacity = .50;
            DrawingRect.SetValue(Canvas.ZIndexProperty, 1000);
        }

    }
}

Now the design surface code is a bit smaller.  The design surface is still assuming the selecting shape is a rectangle but I can fix that in the future.  I will probably also make the selection strategy pluggable at some point. 

Conclusion

Since there are no functional changes I have not updated the live demo.  You can get the most recent code from codeplex.  The final change set as of the end of this article is 28467.  The next AGT few articles will bring more interesting features, and yes I will get back to the Undo framework eventually.

Tags:

History for View Based Navigation in Silverlight 3

by Administrator 22. September 2009 00:17

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.

Tags:

View Based Navigation in Silverlight 3

by Administrator 17. September 2009 01:28

 

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.

Tags:

TwoWay binding to Name/Value Pairs

by Administrator 7. September 2009 18:59

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.

Tags:

Why MEF Matters

by Administrator 16. August 2009 01:30

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.

 

Tags:

About the author

Damon Payne is a Microsoft MVP specializing in Smart Client solution architecture. 

INETA Community Speakers Program

Month List

Page List

flickr photostream