The official Fatica Labs Blog! RSS 2.0
# Monday, 02 May 2011

Sometimes we want to use some shortcut key for special commands in our application, but the KeyBinding objects works with just routed commands, and so it is not directly usable with Caliburn Micro ( or with many other MVVM strategies ).
In similar situation CM rely on System.Windows.Interactivity.dll, for example when we need to map an event on a Caliburn action we can write:

 

 <Button x:Name="Save" >
           
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <cl:ActionMessage MethodName="Save" ></cl:ActionMessage>
                </i:EventTrigger>
            </i:Interaction.Triggers>
 </Button>

 

With the code above, we explicitly link the "Click" event from the button to the action calling the metod Save. We can act in a similar way by creating a custom trigger, lets see how.
First look at what we can do it in XAML:

 

<i:Interaction.Triggers>
        <local:InputBindingTrigger>
            <local:InputBindingTrigger.InputBinding>
                <KeyBinding Modifiers="Ctrl" Key="S"/>
            </local:InputBindingTrigger.InputBinding>
            <cl:ActionMessage MethodName="Save"/>
        </local:InputBindingTrigger>
    </i:Interaction.Triggers>

 

We need to declare a class, deriving from TriggerBase in System.Windows.Interactivity in order to fire the action(s) in place of executing a routed command when the user press the proper key gesture. Here the code:

class InputBindingTrigger:TriggerBase<FrameworkElement>,ICommand
    {
        public InputBindingTrigger()
        {

        }
        public InputBinding InputBinding
        {
            get { return (InputBinding)GetValue(InputBindingProperty); }
            set { SetValue(InputBindingProperty, value); }
        }
        public static readonly DependencyProperty InputBindingProperty =
            DependencyProperty.Register("InputBinding", typeof(InputBinding)
            , typeof(InputBindingTrigger)
            , new UIPropertyMetadata(null));
        protected override void OnAttached()
        {
            if (InputBinding != null)
            {
                InputBinding.Command = this;
                AssociatedObject.InputBindings.Add(InputBinding);
            }
            base.OnAttached();
        }

        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            // action is anyway blocked by Caliburn at the invoke level
            return true;
        }
        public event EventHandler CanExecuteChanged = delegate { };

        public void Execute(object parameter)
        {
            InvokeActions(parameter);
        }

        #endregion
    }

 

Very easily we add the InputBinding to the bindings list on the object, and we attach the trigger as a command handler. In the execute function we fire the InvokeActions and it done. Please not the command on the KeyBinding is not required in the markup, since there is virtually any routed command.

Monday, 02 May 2011 14:16:17 (GMT Daylight Time, UTC+01:00)  #    Comments [8] - Trackback
Caliburn | Recipes | WPF

# Thursday, 28 April 2011

Since is very common to use coroutines for spawn non blocking asynchronous activities in Caliburn Micro (CM), I wrote a simple base class than executes the computation via a BackgroundWorker and ensure the result “Completed” is fired on the same thread who start the call, typically, but not necessary, the UI thread. Here the class:

public abstract class AbstractBackgroundAction:IResult
   {
       abstract protected void OnExecute(ActionExecutionContext context);
       #region IResult Members

       public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };

       public void Execute(ActionExecutionContext context)
       {
           using( BackgroundWorker bw = new BackgroundWorker() )
           {
               Exception exception=null;
               bw.DoWork+=(s,e)=>
                   {
                       try
                       {
                           OnExecute(context);
                       }
                       catch (Exception workException)
                       {
                           exception = workException;
                       }
                   };
               bw.RunWorkerCompleted+=(s,e)=>
                   {
                       Completed(this, new ResultCompletionEventArgs { Error=exception });
                   };
               bw.RunWorkerAsync();
           }
       }

       #endregion
   }
By using the RunWorkerCompleted of the BackgroundWorker we ensure to cam back to the original threads who invoked the coroutine step. Implementer has just to override the function OnExecute.
Thursday, 28 April 2011 17:01:24 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Caliburn | WPF

# Wednesday, 27 April 2011

In this post I will describe a – in order to me – little strange behavior in Caliburn Micro ( CM ) that I discovered in my learning by doing sessions. So the scenario is the following, I have an application with a Main model acting as a screen conductor. The conduced screen are visualized as a classical tabbed application. The exercise goal is to define a visual command on the main view and route it to the proper active item, that is I think a quite common scenario. Let me clarify what I want to achieve with an image:

clip_image001

The TabModel class is actually the model connected to the single tab screen. Lets try to do by just naming conventions:

<Button Grid.Row="0" x:Name="Save"  >
                    <Image Source="assets/disk.png"/>
                </Button>

 

Well, it does not work automatically: CM wire just the MainModel, so we need to explicitly re-target the action on the Active child:

<Button Grid.Row="0" x:Name="Save"  cl:Action.TargetWithoutContext="{Binding Path=ActiveItem}">
                    <Image Source="assets/disk.png"/>
                </Button>
Unfortunately message is not routed yet. Let’s try to define the message handler in the main model:
class MainWindowModel:Conductor<object>.Collection.OneActive
   {
       public MainWindowModel()
       {
           Items.Add(new TabModel("Tab 1"));
           Items.Add(new TabModel("Tab 2"));
           Items.Add(new TabModel("Tab 3"));

       }
      
       public void Save()
       { 
       }
   }
Well, it works !
image 

This is because CM creates the poper handler in the main model, so it can route it when we re-target the handler. Since this is probably not the desired behavior, it is probably better to use this strategy instead:

 

<Button Grid.Row="0" x:Name="Save"  
cl:Message.Attach="[Event Click] = [Action Save()]"  
cl:Action.TargetWithoutContext="{Binding Path=ActiveItem}">
                    <Image Source="assets/disk.png"/>
</Button>
By doing this we leave the naming convention strategy, and we explictly declare what we want to do, is better to avoid unpredictable behavior :)
If you are interested in the code for reproducing this check this issue.
Wednesday, 27 April 2011 16:59:28 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Caliburn | WPF

# Sunday, 24 April 2011

If you are used to works with Winform, you probably feel being less productive in WPF, but this can be overtaken by approaching the design the correct way, and with proper tools productivity would be the same as Winform, and probably better. MVVM seems to be the right pattern to cleanup the scaring and messy stuff polluting the XAML and the code behind on the view. There is some framework to help to do this, and I choose Caliburn  for this sample application, but I think the idea is the important part, so let’s try and compare. By the way, it worked for me trying to write my own MVVM framework, this increase the learning curve gradient when we go for another more proven and stable solution. If you want follow this suggestion you probably would look at this very famous video about MVVM, edited by the author of Caliburn, Rob Eisenberg. Rob is a man that look at the mess in the XAML and said: Ok let’s create something to clean up this, instead of start up again with a WinForm app Smile. So let’s talk about the app, should be simple but doing something interesting, and must take 1/2 hour to write. I decided to write a Flickr picture browser so there is as well some async call to web services to show.

Let’s prepare our toolbelt for start we need to:

So start the application and put the required dependencies in the Lib folder of the solution, so we have something like this at the end:

image

All this reference are dependencies of our app, and with this we are ready to start to write the application itself. We start to “bootstrapping” the application. We have a main window for our application, and this will be our application main View, and we need to stick to it a ViewModel. Caliburn can do this automatically in the boostrap phase, lets see.

First create a class deriving from Botstrapper<T> where T is our ViewModel. As below:

class Boot:Bootstrapper<MainWindowModel>
{

This class can be empty to start, we come back later, now we modify the App.Xaml markup, by removing the StartupUri and adding a bootstrapper instance as a resource, so an instance will born:

<Application x:Class="FlickAndFlock.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:FlickAndFlock">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:Boot x:Key="Boot"></local:Boot>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Window">
                <Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

If we launch the application at this point, the main window appear anyway, why ?

image

Because Caliburn infer the main window to start from the view model class name. The default convention is that the view has the same type name as the model minus “Model”, so if our model is MainWindowModel, the view to launch is MainWindow. So what happened in the boot was:

ViewModelBinder-INFO:Binding FlickAndFlock.MainWindow and FlickAndFlock.MainWindowModel.
Action-INFO:Setting DC of FlickAndFlock.MainWindow to FlickAndFlock.MainWindowModel.
Action-INFO:Attaching message handler FlickAndFlock.MainWindowModel to FlickAndFlock.MainWindow.

As I can see in my trace output in Visual Studio after having set up the log in the boot class static constructor:

static Boot()
{
     LogManager.GetLog = t => GetLogger(t);
}

We overwritten the function GetLog of LogManager with our one, returning an instance of a class implementing ILog that just dump the messages on the trace. Having a log enabled is a good idea when we have a convention over configuration based framework. Sometimes we don’t understand why convention are not applied as we expect, and usually we can guess where the problem is by looking at the log. Another point here is how we change the log recovering strategy: by setting a function to a property. This way of customization is cross used in the entire Caliburn framework. So as you probably guessed, if we want to change the way we look for the view from the model name, the strategy is exactly the same:

ViewLocator.LocateTypeForModelType = (modelType, displayLocation, context) =>…

 

In the example application we used the default one, but is good to know that if does not feet our convention, we can change.

So now we have the main view,and the main ViewModel, but what exactly we can put inside the ViewModel ? Well we can think the ViewModel as a model oriented to the presentation, focalized on the view, not on the business logic. Is the ViewModel to that is notified about the UI events, ie the “Actions” the user want to do.

We proceed now to add some user control on the XAML to allow the user to search by tag the Flicker photo database, obtaining something like:

image
<StackPanel Grid.Column="0">
            <TextBlock Margin="20">Tag:</TextBlock>
            <TextBox Margin="20" x:Name="Tags"></TextBox>
            <Button Margin="30,20,30,20" IsDefault="True" x:Name="Search">Search Flickr</Button>
            <StackPanel Orientation="Horizontal">
                <Button Margin="10,10,10,10" Width="80"  x:Name="PrevPage">Previous</Button>
                <Button Margin="10,10,10,10" Width="80" x:Name="NextPage">Next</Button>
            </StackPanel>
        </StackPanel>

The XAML is quite simple, there is nothing related to events in it, but, as you can see from the picture, previous and next are disabled, and search is not. This is another Caliburn magic, let see what’s in the log:

ViewModelBinder-INFO:Action Convention Applied: Action Search on element Search.
ViewModelBinder-INFO:Action Convention Applied: Action NextPage on element NextPage.
ViewModelBinder-INFO:Action Convention Applied: Action PrevPage on element PrevPage.

ViewModelBinder-INFO:Binding Convention Applied: Element Tags.

ActionMessage-INFO:Action: Search availability update.
ActionMessage-INFO:Action: Search availability update.
ActionMessage-INFO:Action: PrevPage availability update.
ActionMessage-INFO:Action: PrevPage availability update.
ActionMessage-INFO:Action: NextPage availability update.
ActionMessage-INFO:Action: NextPage availability update.

As we can see inside the log, the framework found some methods in our ViewModel called as the x:Name on the UIelement, so it automatically wired it. Even the command availability is automatically wired to property called Can+action name. Similar sort was reserved to the TextBox, automatically bound to the property Tags.

Let’s have a look now on how the command are actually implemented. Here the search function:

 

       public IEnumerable<IResult> Search()
       {
           currentPage = 1;
           return PageSearch();
       }
       public IEnumerable<IResult> PageSearch()
       {
           Thumbs.Clear();
           yield return new Wait(true);
           yield return new Search(Tags, currentPage);
           yield return new Wait(false);
           NotifyOfPropertyChange(() => this.CanNextPage);
           NotifyOfPropertyChange(() => this.CanPrevPage);
       }

That’s could sound a little strange. The routine is returning an IEnumebrable<IResult>, what is this ? Well this is a strategy to make easy and readable code when we need to spawn asynchronous process, wait for the result, then go on with something else, and so on. This can result in a lot of messy code and complicated lambdas. By returning ( or better, Yielding ) an IResult we return an object that is capable to do something and signal when done. As a consequence, functions cooperate together and all returns in the “master” function, that is called CoRoutine. Not really a new idea since comes from Knuth, but in fact C# has not a native way of express such a context. Result are obtained in C# by an orchestration part ( implemented in Caliburn ) and leveraging the yield statement to leave and re-enter the main routine. I think it is interesting to know that someone creates the same strategy before the yield statement were created ( NET 2.0 ), have a look here if you are courious. It is important to know that implementing the acgtions as CoRoutines is not mandatory, but is strongly encouraged when you have to deal with sync-async calls wired together.

Before ending, let’s have a look on how we wire an IoC to that strategy. This is done by customizing the bootstrapper, here an example:

           protected override object GetInstance(Type service, string key)
           {
               return kernel.Get(service);
           }

 

Caliburn call the function above when he need to instantiate an object, or when we try to instantiate something using the IoC static class. So that function is the extension point to bind the container. In the simple application I bound NInject, but any container can probably fit the purpose. Note that, even if you use the static IoC, without customizing the bootstrapper, natively Caliburn does not perform any IoC, but just plainly creates the requested type.

So the application is finished:

image

And we manage to avoid writing any code inside the view. And it is not all, Caliburn Micro has a lot of feature for us, even remaining a thin framework.

Sunday, 24 April 2011 00:03:42 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Programmin | Recipes | WPF

# Tuesday, 05 April 2011
Cannot start test project “xxxx” because the project does not contains any tests

This error happen when we try to launch a Visual Studio Project defined as test with another testing framework ( ie NUnit ) and we remove all the visual studio test from inside it. To me happened when I try to revert back to NUnit a project with standard Visual Studio tests. Here The message:

clip_image001

 

The solution is to open the project ( csproj ) file with a text editor, and look for the lines below:

image

 

By removing the line in evidence we go back to a standard class library project and the problem is solved.

Tuesday, 05 April 2011 09:58:33 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Programmin | Tips

# Friday, 01 April 2011

Just a little post about this argument, since as the author of (t4) Hbm2net and Db2hbm I think I can say my opinion from a critic point of view. As an user I can say that, as an OR/M NHibernate is a great platform, almost any circumstances are treated in deep, and even the infamous “legacy db from hell” are gently handled. So this some of my thought:

ONE -  Mapping is not always monkey coding.

This comes from the experience from Db2hbm. The tool can be great if you ( as me, as everybody at the start/half part of the learning curve ) have to start with a big database, and you don’t want to do all the job by hand. Db2hbm has a strategy called mapping exception, you can use it to customize the mapping, but the product is actually monkey code, and you need to abandon the automatic lifecycle in favor of custom mapping. This is bad in term of code generation, since the difference between a code generator that works almost 90% the time and one that works 100% of the time is a lot more than 10% Smile.

TWO – Writing class is monkey coding. 

This comes from hbm2net. I worked personally on the old version in the NHContrib and produced a version with a T4 template. I never modified the template and always had a working class for my mapping, even with exotic associations. This is really pleasant, since we already did a boring job in writing the hbm, creating the class from it would be just painful. So, in my experience, there is nothing more in the class that is not already said in the hbm.

THREE – Xml is not the devil

There is nothing painful in writing XML if we enable the intellisense for it. It is easier to grab all the mapping details by writing your own mapping, and at soon you have a a good practice, you can leverage some nh mapping sugar, to deal with really powerful mapping constructions. With the meta tag hbm can collect even more information to feed more code generators.

FOUR – Fluent NHibernate

Fluent NHibernate is the ( probably most famous ) way to avoid writing XML with NHibernate. Even of there is an AutoMapping feature, that does avoid wrtite any code, you eventually ends writing such things:

public class CatMap : ClassMap<Cat>
{
  public CatMap()
  {
    Id(x => x.Id);
    Map(x => x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x => x.Sex);
    References(x => x.Mate);
    HasMany(x => x.Kittens);
  }
}
So if it is monking code writing the class for HBM, here you monkey twice by writing two class for say the same thing. 

FIVE – ConfOrm

CodeConform is the newest, and maybe the most innovative no xml mapping strategy. Fabio Maulo inspired himself probably in this post. The main idea in Conform in order to me is the pattern strategy that can help write complex mapping without really having to touch any xml file. The xml layer is avoided even internally, so loading a session factory is sensibly faster.  Since Fabio is the lead developer of NHibernate, some of these concept will probably appear on the next NH version.

Conclusion – What I would like to see

I like code first OR/M. But in real life this happened to me 0 times. So having legacy DB ( well, DB first approach, that is the same ) is quite common for me, and I think for a lot of people. Write a mapping in code is not an option, or does not make sense in order to replace hbm, we eventually fall in duplicate the concepts. ConfOrm by design avoid composite key, that are really common in legacy schemas. We need something to easily grab the pattern the DB designer would mean and easily port it to our NH solution.

Friday, 01 April 2011 22:25:13 (GMT Daylight Time, UTC+01:00)  #    Comments [2] - Trackback
NHibernate

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2019
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 127
This blog visits
All Content © 2019, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano
Nike Winkels Nederland Outlet Nike Nederland Store Outlet Nike Nederland 2015 Outlet Nike Outlet Online Nike Sneakers Outlet