Geeks With Blogs
Josh Reuben

I dont know about you, but last year I suffered from MVVM overdose. I literally felt sick having to go through the rote task of building the same old Prism modules and building the same old ViewModel to abstract my Model, setup my bindings in my view .... again and again and again and again .... ad nausium.

Now that I've had a break from client side information system dev, I can think about it from a different perspective. I've leveraged and investigated the following technologies. 

1) Cinch from Sascha Barber - http://cinch.codeplex.com/ - alot of useful (and well tested) client side infrastructure here - At my main customer last year, everyone on a large client side team built their own infrastructure silos without documenting or informing the team (guys, you know who I am taliking about!!!). the square wheel was reinvented many times. So I say, use Cinch.

2) ReactiveUI - http://www.reactiveui.net/ - while this framework is a little rough arround the edges, by leveraging the RX enabled ReactiveCommand, ReactiveCollection and ReactiveObject classes,  I was quickly able to build ICommand state machines and their pipeline dispatchers. Observables are definately the way of the future.

3) MVMMapper http://mvmmapper.codeplex.com/  this simple set of T4 templates lets you generate your ViewModels from your Model POCO / DTOs. nice.

4) VMSDK (The Visual Studio Visualization and Modeling SDK) - this is what all the Visual Studio UML designers and the Entity Framework EDMX Designer was built with. It is a DSL for buildig DSLs which then generate code via T4. Powerful stuff - I strongly urge you to explore the lab here: http://code.msdn.microsoft.com/DSLToolsLab. Will blog more about this in the future.

Anyway, I've been constructing a DSL + Designer + code generator for end-to-end code pipelines. One issue I had was Bindings were embedded all over the place within Views. In order to map and generate a pipeline, I needed to abstract the bindings out of the view. for example (simulating a binding to a VM):

        <UniformGrid Columns="2">        
            <TextBox x:Name="Source"/>  
            <TextBox Text="{Binding ElementName=Source, Path=Text}"/>

First thing I did was introduce a level of indirection - I created a FrameworkElement (supports binding and insertion into Visual Tree)  that exposed 2  dependency properties: Source and Target.  I handled sync between the two in the PropertyChangedCallback:

    public class BindingMap : FrameworkElement
    {
        #region Source
        public object Source
        {
            get { return GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }
 
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source"typeof(object), typeof(BindingMap), new UIPropertyMetadata(null, SourcePropertyChanged));
 
 
        static void SourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var b = o as BindingMap;
            if (b == nullreturn;
            if (b.Target == e.NewValue) return;
            b.Target = e.NewValue;
 
        } 
        #endregion

I then created an ItemsControl to contain this (will make this strongly typed later).

public class BindingMapCollection : ItemsControl {}

Following this I created a datasource type that i could leverage decleratively to expose an array:

public class BindingMapCollectionSource
    {
        public BindingMap[] BindingMaps { getprivate set; }
        public BindingMapCollectionSource(BindingMap[] array)
        {
            BindingMaps = array;
        }
    }

I changed my code so that both source and target objects were named, but knew nothing of each other.

<UniformGrid Columns="2">        
            <TextBox x:Name="Source"/>
            <TextBox x:Name="Target"/>           
        </UniformGrid>

I created ResourceDictionary that contained an ObjectDataProvider for exposing my BindingMaps: It initialized the BindingMapCollectionSource with an array of BindingMap elements:

 

I would also consider placing any DataTrigger declerations in BasedOn styles within such a dictionary. We are seperating Binding from the perview of the Designer!

To use, add 1 line to the View:

<WpfAbstractBinding:BindingMapCollection ItemsSource="{Binding Source={StaticResource BindingsMapDataProvider}, Path=BindingMaps}" />
        

thats it!

Some workarrounds may be needed to get this to work with nested templates, but it is doable.

The point is, I can now easily generate my bindings ResourceDictionary from T4 - further down the road, I may use the VMSDK to construct a Biztalk style mapping DSL Designer and leverage the VS2010 Binding Editor for this.

I hope you enjoyed this post!

<ObjectDataProvider x:Key="BindingsMapDataProvider"
                            ObjectType="{x:Type WpfAbstractBinding:BindingMapCollectionSource}">
            <ObjectDataProvider.ConstructorParameters>
                <x:Array Type="{x:Type WpfAbstractBinding:BindingMap}">
                    <WpfAbstractBinding:BindingMap Source="{Binding ElementName=Source, Path=Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                                   Target="{Binding ElementName=Target, Path=Text,  UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
 
                    <WpfAbstractBinding:BindingMap></WpfAbstractBinding:BindingMap>
                    <WpfAbstractBinding:BindingMap></WpfAbstractBinding:BindingMap>
                </x:Array>
            </ObjectDataProvider.ConstructorParameters>
        </ObjectDataProvider>
Posted on Wednesday, March 30, 2011 1:01 PM XAML | Back to top


Comments on this post: MVVM DSLs and XAML Binding Abstractions

# re: MVVM DSLs and XAML Binding Abstractions
Requesting Gravatar...
That's a great article -- you mentioned some things already on my list, which I need to get to, and added some new interesting Codeplex projects.
Do you 'role your own' MVVM?
-- Thanks
Left by Chris on Mar 30, 2011 6:12 PM

# re: MVVM DSLs and XAML Binding Abstractions
Requesting Gravatar...
This is great! I think, I have to consider using some of these technologies. - Paradise Home Improvement Charlotte
Left by Michael Douglas on Dec 22, 2016 11:42 AM

Your comment:
 (will show your gravatar)


Copyright © JoshReuben | Powered by: GeeksWithBlogs.net