The official Fatica Labs Blog! RSS 2.0
# Thursday, 03 November 2011

As we know the Caliburn Micro library implements a screen conductor to handle multiple screen models with only one active, typically used for tabbed views, that is easy to implement by deriving your model from Conductor<IScreen>.Collection.OneActive. This works out of the box with the standard tab control, but it is not possible to use it for example with the tabbed documents in AvalonDock. The only solution I found, that for some reason I will say below, is this one. I don’t like this solution because it force to write code inside the view, that is not acceptable in a pure MVVM solution, so I preferred to insulate the code in an attached behavior. In addition the presented solution will works correctly with the Activate/Deactivate/CanClose strategy on each document. We just need to modify the view markup as in the example below:

As you can see we just added an attached property UseConductor.DocumentConductor that we bind to the current model. Of course the model is a OneActive screen conductor. The behavior take care to connect the document items of the DocumentPane with the screen conductor items. If each screen implements IScreen, the proper Activate/Deactivate/CanClose are called, so we can even handle the case of canceling the close of a dirty document. Here the attached behavior code: An example MainModel can be the following one:

( we just add some random document to see how it behave )

And here below an example of a single screen  model:

So we have the conductor, without touching the view code, and without creating a custom screen conductor.

Thursday, 03 November 2011 19:52:59 (GMT Standard Time, UTC+00:00)  #    Comments [6] - Trackback
Caliburn | WPF | CodeProject

# Tuesday, 11 October 2011

As I said in this post I' have been working on an helper library to encapsulate the extra work we should do in presenting big dataset to the user: limiting the resultset. I wrote a 5 minutes demo to show how the interface could appear reactive, based on NHibernate - Caliburn-and FlyFetch. This does not mean that Flyfetch depends on some way on these library, is just to have something to show very quickly. The present FlyFetch version is not bound to any presentation technology to ( even if RIA and WPF applications are probably the best candidates to use ).   The application requires to have AdventureWorks to so since the prerequisite are not trivial I decided to grab a little video of the sample app running, just to show the reactivity we can achieve with FlyFetch.

FlyFetch in a demo app

I managed to remove any proxy engine dependency ( I use an internal proxy factory to create a special custom proxy ), and I managed to have an MVVM friendly component since the pager works independently from the view.You are welcome to follow FlyFetch at this address, or simply fork your version here. As an update, I used flyfetch with success in production too :)

Tuesday, 11 October 2011 20:54:13 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
CodeProject | FlyFetch | MVVM | WPF

# Friday, 07 October 2011

The current implementation using SynchroVisible and With fails when there is more than three chart to synchronize. So I modified the code and added a central agent to keep in synch more charts. We just need to define an instance of it as a resource:

<Window.Resources>
       …

        <ddd:MultiChartSynchronizer x:Key="mainSynchro"/>
    </Window.Resources>

and then “subscribe” each chart to keep in synch with:

<ddd:ChartPlotter x:Name="price" ddd:SynchroVisible.Axis="X" 
ddd:SynchroVisible.Using="{StaticResource mainSynchro}"
LegendVisibility="Hidden" NewLegendVisible="False" Grid.Row="1">
image 

obviously we can have multiple instance of synchronizer object to create more context in which chart align.

You can find and follow this project on Bitbucket.

Friday, 07 October 2011 17:24:31 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
D3 | WPF

# Thursday, 06 October 2011

One of the most important feature to make a data based application reactive is to limit the resultset returned to the GUI. This is usually done in two places: the service implementation that must support some ranking strategy, and the GUI itself that has to leverage these features to show the user just the portion he need ( or he see ). I implemented an almost generic solution for WPF at work that leverage Linfu.DynamicProxy. The strategy consist in filling the (observable)collection with some fake objects that by interception drive the underlying data source to fetch the items in pages just when the user actually see them. I like that solution, but it introduces an extra dependency that I prefer to avoid, and indeed the proxy feature I need are so simple that an entire fully fledged library is too much. So I started a project that aims to be:

  • Zero dependency
  • Single file ( can add to your project without referencing any dll )
  • Never blocking the GUI
  • Easy to use
  • Data source independent
  • MVVM friendly

Here is the first start if you want to see, and contribute with ideas and suggestions. The name stays for Flyweight pattern Fetching strategy. The current solution is under development, don’t download if you need a running solution. I usually post just when things are in some way usable, this is an exercise for me too: presenting a work at its very early stages, in the hope to have contributions to create something *better* Smile

Update: here is some progress

Thursday, 06 October 2011 21:12:40 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
CodeProject | MVVM | WPF

# Tuesday, 09 August 2011

Sometimes it is annoying that the TextBox in WPF needs to loose focus in order to updating the underlying value in the model. Having the application moving the focus in order to force the binding update is a bad trick, unacceptable if you are using MVVM. In such a case worked for me deriving a custom class from the textbox ( actually I did for the Fluent Ribbon textbox, but the concept is the same ) and programmatically updating the source, as below:

public class UpdatingBindingTextBox:TextBox
    {
        public UpdatingBindingTextBox()
        {
            this.TextChanged += new System.Windows.Controls.TextChangedEventHandler(UpdatingBindingTextBox_TextChanged);
        }

        void UpdatingBindingTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            BindingOperations.GetBindingExpression(this, TextBox.TextProperty).UpdateSource();
        }
    }
So this force the model to update at each character in input.

ADDITION:

By investigating a little more, I found this alternative on stack overflow. It is basically a behavior attached to the textbox that call a command in the ViewModel. Don’t know which one is better, I personally like the behavior way, but in any case I do need to update the binding manually into the view model…

Tuesday, 09 August 2011 16:16:06 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
WPF

# Thursday, 21 July 2011

If you plan to use the Caliburn Micro convention with buttons contained in a Fluent Ribbon you will notice that it does not works out of the box. This is because the default BindingScope.GetNamedElements does not dig inside the ribbon to looks for named control. The solution that worked for me is to modify the default behavior as swown below:

In the overridden Configure function:

defaultElementLookup = BindingScope.GetNamedElements;
           BindingScope.GetNamedElements = new Func<System.Windows.DependencyObject, IEnumerable<System.Windows.FrameworkElement>>(
               k =>
               {
                   List<FrameworkElement> namedElements = new List<FrameworkElement>();
                   namedElements.AddRange(defaultElementLookup(k));
                   Fluent.Ribbon ribbon = LookForRibbon(k);
                   if( null != ribbon )
                       AppendRibbonNamedItem(ribbon, namedElements);
                   return namedElements;
               }
               );

We need to define defaultElementLookup into the boot class as:

Func<DependencyObject, IEnumerable<FrameworkElement>> defaultElementLookup;
I saved the standard GetNamedElement function because I use it to look for the control the default way, and to look for the controls inside the Ribbon too.

Here the function LookForRibbon, that just dig into the visual tree to search for a ribbbon ( if any ):

private Fluent.Ribbon LookForRibbon(DependencyObject k)
        {
            Fluent.Ribbon foundRibbon = null;
            var contentControl = k as ContentControl;
            if (null != contentControl)
            {
                var child = contentControl.Content as DependencyObject;
                if( null != child )
                    return LookForRibbon(child);
            }
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(k); ++i)
            {
                var child = VisualTreeHelper.GetChild(k, i);
                foundRibbon = child as Fluent.Ribbon;
                if (null != foundRibbon)
                {
                    return foundRibbon;
                }
                else
                {
                    foundRibbon = LookForRibbon(child);
                    if (null != foundRibbon)
                        return foundRibbon;
                }
            }
            return null;
                
        }

 

As you guess, the function stops at the first found ribbon so we suppose there is just one ribbon for view ( quite reasonable )

As we have the ribbon we can look for the elements inside and append to the list with this function:

 

private void AppendRibbonNamedItem(Fluent.Ribbon ribbon, List<FrameworkElement> namedElements)
        {
            foreach (var ti in ribbon.Tabs)
            {
                foreach (var group in ti.Groups)
                {
                    namedElements.AddRange(defaultElementLookup(group));
                }
            }
        }

 

So we look inside each ribbon group and we treat these as Caliburn would do.

Thursday, 21 July 2011 14:35:52 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Caliburn | WPF

# Tuesday, 07 June 2011

Sacha Barber expand his work on a very famous project presented about 4 years ago on CodeProject. It is a very interesting project about class diagram creation in WPF, mainly because is a good field for learning advanced WPF functionality. Here Sacha explain the new version, and below a screen shot:

Tuesday, 07 June 2011 20:22:55 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
WPF

Just add a new feature to decide where to place the vertical axis: left or right aligned to the plot area. Here the property usage:

<ddd:ChartPlotter MainVerticalAxisPlacement="Right"  >

 

A modification was necessary even in the WidthSpring element, the one that allow us to keep more than one chart synchronized on the X axis ignoring the space taken by the label area. It is now possible to specify that the WidthSpring must act on the left of the chart. Here the usage with the new properties:

<ddd:WidthSpring ActiveOnSide="Right" SourcePanel="{Binding RightPanel, ElementName=volume}"/>

 

by this addition the chart behave correctly even with the right side placed vertical axis:

r4

Source for this project can be found here.

Tuesday, 07 June 2011 20:15:50 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
D3 | WPF

# Wednesday, 01 June 2011

The current ( trunk ) implementation of Caliburn Micro introduces a new element in the phase of obtaining the view type name from the model name. The name of the View type is obtained from the name of the ViewModel type by applying a series of rules based on RegEx match and replace patterns. These rules has some defaults values, but others can be added externally by calling

NameTransformer.AddRule

There is an important default that is given by the following pattern:

NameTransformer.AddRule("Model$", string.Empty);

 

This is the rule that allow old model view naming convention works properly.

If you have some not up-to-date trunk version you can experience some problem, have a look at this discussion. The current doc of NameTrasformer is the source code of the ViewLocator and the ViewModelLocator from which you can derive what conventions are applied.

Wednesday, 01 June 2011 13:41:00 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Caliburn | WPF

# Wednesday, 25 May 2011

In  the previous sample we shown how to present multiple chart by keeping them aligned in order to be comparable on the horizontal axis by using the WidthSpring feature. But D3 charting can automatically pan and zoom ( both by rect zoom by pressing control and left dragging the mouse on the chart, or by the wheel ) and in this case we loose the axis synchronization. Here below the undesired behavior:

image On the left we see the top chart zoomed, the other ones show the horizontal range thus there is no more relation among the three charts.

So we create an attached property as below:

<ddd:ChartPlotter x:Name="price" ddd:SynchroVisible.Axis="X" ddd:SynchroVisible.With="{Binding ElementName=volume}" …>
 

by applying this property we choose which axis synchronize ( X in the example, but can be Y or XY ) and which chart keep synchronized with, in this case we bind with the chart named “volume”. By repeating the property two chart by two chart:

<ddd:ChartPlotter x:Name="volume" ddd:SynchroVisible.Axis="X" ddd:SynchroVisible.With="{Binding ElementName=ma}" …>
<ddd:ChartPlotter    x:Name="ma"  ddd:SynchroVisible.Axis="X" ddd:SynchroVisible.With="{Binding ElementName=price}" …>

 

so we achieve this interesting result without any code behind:

image This is the result after panning the chart ( by dragging the mouse pointer into the chart area in any of the three chart ) as you can see the other chart properly follow…
image The same apply if we zoom on the chart area ( by pressing ctrl while dragging, or by the mouse wheel ) other chart amplify the resolution on the synchronized axis and the start position accordingly.

Check out the source for this example here.

Wednesday, 25 May 2011 21:49:37 (GMT Daylight Time, UTC+01:00)  #    Comments [5] - Trackback
Charting | D3 | WPF

# Monday, 23 May 2011

Since contacting the original team for sending patches did not success, I decided to share my sources here. You find the bar chart and the candlestick I was talking in this previous post. Hope you find this useful.

Monday, 23 May 2011 11:53:56 (GMT Daylight Time, UTC+01:00)  #    Comments [3] - Trackback
Chart | Dynamic Data Display | WPF

# Tuesday, 17 May 2011

This post dig a little more into this blog post code about working with and customizing Dynamic Data Display charting. Since the default bar chart implementation does not work, it’s easy to create our own by simply deriving one chart from PointGraphBase.

 

public class BarChart : PointsGraphBase
{

Then we define the classical bounch of dependencies properties which code is not so fancy to see: Thickness, Stroke and fill brush, and so on. The core function we must implement is OnRenderCore. Let’s see how:

protected override void OnRenderCore(System.Windows.Media.DrawingContext dc, RenderState state)
       {
           if (DataSource == null) return;
           var transform = Plotter2D.Viewport.Transform;

           DataRect bounds = DataRect.Empty;
           using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext()))
           {
               Point point = new Point();
               while (enumerator.MoveNext())
               {
                   enumerator.GetCurrent(ref point);
                   enumerator.ApplyMappings(this);

                   Point zero = new Point(point.X, 0);
                   Point screenPoint = point.DataToScreen(transform);
                   Point screenZero = zero.DataToScreen(transform);

                   double height = screenPoint.Y - screenZero.Y;

                   if (height >= 0)
                   {
                       dc.DrawRectangle(Fill, new Pen(Stroke, StrokeThickness)
, new Rect(screenPoint.X - BarWidth / 2, screenZero.Y, BarWidth, height));
                   }
                   else
                   {
                       dc.DrawRectangle(Fill, new Pen(Stroke, StrokeThickness), 
new Rect(screenPoint.X - BarWidth / 2, screenPoint.Y, BarWidth, -height));
                   }

                   bounds = DataRect.Union(bounds, point);
                   
               }
           }

           Viewport2D.SetContentBounds(this, bounds);
       }
So nothing really special, just some key point:
 
  • ApplyMapping is the function who map the model coordinates into the graphical X-Y coordinates.
  • DataToScreen/ScreenToData are the (extension) method who maps from world coordinates to screen coordinates.
 
The other code is just drawing the rectangles for each point at a certain bar width, and we obtain this:
image
 

 

 

As you can probably see, line are anti-aliased even if we specified SnapToDevicePixels. This is due to the fact that SnapToDevicePixels does not work when we manually draw onto a DrawingContext. If we want to remove this we need to follow these instructions and create some GudelineSet to force WPF align to physical bytes.

Tuesday, 17 May 2011 21:50:48 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Charting | D3 | WPF

# Monday, 16 May 2011

By extending the generic helper class proposed for a generic CoRoutine in Caliburn Micro it is easy to create an helper that we can use this way:

public IEnumerable<IResult> SourceChange()
       {
           yield return new CoMethod(() => { PriceDS = CreateDataSource(SelectedSource); });
           NotifyOfPropertyChange(() => this.PriceDS);
           yield return new CoMethod(() => { VolumeDS = CreateDataSource(SelectedSource); });
           NotifyOfPropertyChange(() => this.VolumeDS);
           yield return new CoMethod(() => { Mavg5DS = CalculateMAverage(SelectedSource,5); });
           NotifyOfPropertyChange(() => this.Mavg5DS);
           yield return new CoMethod(() => { Mavg10DS = CalculateMAverage(SelectedSource, 10); });
           NotifyOfPropertyChange(() => this.Mavg10DS);
       }

In a single line we invoke asynchronously a method without having to crate a class implementing IResult. By the way this code is the one that creates the sources for the charts in this blog post.

The helper class is pretty easy:

public class CoMethod:AbstractBackgroundAction
    {
        Action toRun;
        public CoMethod(Action toRun)
        {
            this.toRun = toRun;
        }

        protected override void OnExecute(Caliburn.Micro.ActionExecutionContext context)
        {
            toRun();
        }
    }
It just invoke the action in the BackgroundWorker.
Monday, 16 May 2011 20:24:07 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Caliburn | WPF

# Sunday, 15 May 2011

I was looking for a good open source charting library and I noticed that is a little difficult to find something really useful and easy to use. I had a look at the WPF Toolkit charting library, a little old for sure, but look promising at a first glance. Unfortunately it is not so easy to use, not brilliant in term of speed and with some discutable behavior,  as for example the absence of a way to remove the chart animation, or removing the fancy bullet in the line chart. By digging a little deeper I found the WPF Dynamic Data Display

imageEven if it seems not recently updated in term of source code, it has a professional level functionality, easy to customize and use, and with some effort MVVM compatible. Make sure to download the unreleased latest source changeset because it is dramatically different from the released one. Here below we show hoe to use this charting library for a very common task, creating multiple chart with the same X Axis. The goal is to have the classical view of a stock chart: Candlestick+Volume some indicators. As a surprise we can see that the latest changeset does not have out of the box any candlestick chart, neither is possible to display a proper bar chart ( there is an OldBarGraph in the code, but it does not seems to work anymore ). Well this is not generally a problem, since a good charting library should be extensible in some way, so we try to create our chart by extending the existing ones. Before to go on let’s have a look on the sample application:

image

The application, even if simple, uses Caliburn Micro, have a look here if you need some notes about that. Data are embedded resources obtained fro YAHOO! Finance for the sole purpose of writing this example application. So lets start with the candles. We note in the source code bounch that exists a MarkerPointsGraph, a graph that display a Marker at each “Y” coordinate, so couldn’t be the candlestick a marker ? Yes, by just deriving from PointMarker. Let see how “difficult” this can be:

 

public class CandleStickPointMarker:ShapePointMarker,ITransformAware
   {
       
       
       public override void Render(System.Windows.Media.DrawingContext dc, Point screenPoint)
       {
           Point screenOpen = GetScreenPoint(Open,screenPoint.X);
           Point screenHigh = GetScreenPoint(High,screenPoint.X);
           Point screenLow = GetScreenPoint(Low, screenPoint.X);
           //screenPoint is the CLOSE by gentleman agreement.
           var close = screenPoint.ScreenToData(Transform).Y;
           Pen strokePen;
           if (Open >= close) // black
           {
               strokePen = new Pen(BlackCandleStroke, CandelstickStrokeWidth);
               var h = -screenOpen.Y + screenPoint.Y;
               dc.DrawRectangle(BlackCandleFill,strokePen 
                   , new Rect(screenPoint.X - CandelstickWidth / 2, screenOpen.Y, CandelstickWidth, h)
                   );
               dc.DrawLine(strokePen, screenLow, screenPoint);
               dc.DrawLine(strokePen, screenHigh, screenOpen);
           }
           else // white
           {
               strokePen=new Pen(WhiteCandleStroke, CandelstickStrokeWidth);
               var h = screenOpen.Y - screenPoint.Y;
               dc.DrawRectangle(WhiteCandleFill, strokePen
                   , new Rect(screenPoint.X - CandelstickWidth / 2, screenPoint.Y, CandelstickWidth, h)
                   );
               dc.DrawLine(strokePen, screenLow, screenOpen);
               dc.DrawLine(strokePen, screenHigh, screenPoint);
           }
       }

       private Point GetScreenPoint(double Open,double screenX)
       {
           Point screen = new Point(0, Open);
           return new Point(screenX,screen.DataToScreen(Transform).Y);
       }
   }

Really easy, we just need a trick: since the marker currently works with a pre-transformed coordinate for the single point the marker usually represent, and we need instead other three value ( Open/Min/Max ) we need to transform these value recovered directly from the data source. This is the reason I had to create the interface ITransformAware , so we can pass the transform to the PointMarker, let see how:

using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext()))
            {
                Point point = new Point();
                while (enumerator.MoveNext())
                {
                    enumerator.GetCurrent(ref point);
                    enumerator.ApplyMappings(Marker);

                    //Point screenPoint = point.Transform(state.Visible, state.Output);
                    Point screenPoint = point.DataToScreen(transform);

                    bounds = DataRect.Union(bounds, point);
                    var ta = Marker as ITransformAware;
                    if( null != ta )
                        ta.Transform = transform;
                    Marker.Render(dc, screenPoint);
                }
            }

This is the only trick. DataSOurce side what we have to do is to add the mapping for the missing coordinates:

 

               value.SetYMapping(k => double.Parse(k[4], CultureInfo.InvariantCulture));
               value.AddMapping(CandleStickPointMarker.OpenProperty, k => double.Parse(k[1], CultureInfo.InvariantCulture));
               value.AddMapping(CandleStickPointMarker.HighProperty, k => double.Parse(k[2], CultureInfo.InvariantCulture));
               value.AddMapping(CandleStickPointMarker.LowProperty, k => double.Parse(k[3], CultureInfo.InvariantCulture));

Xaml Side:

<ddd:ChartPlotter x:Name="price"    LegendVisibility="Hidden" NewLegendVisible="False" Grid.Row="1">
            <ddd:VerticalAxisTitle>Price</ddd:VerticalAxisTitle>
            <ddd:WidthSpring SourcePanel="{Binding LeftPanel, ElementName=volume}"/>
            <ddd:MarkerPointsGraph DataSource="{Binding PriceDS}"  >
                <ddd:MarkerPointsGraph.Marker>
                    <ddd:CandleStickPointMarker WhiteCandleFill="Azure" BlackCandleFill="DarkBlue">
                        
                    </ddd:CandleStickPointMarker>
                </ddd:MarkerPointsGraph.Marker>
            </ddd:MarkerPointsGraph>
            <ddd:ChartPlotter.MainHorizontalAxis>
                <ddd:NumericAxis LabelProvider="{StaticResource tickToDate}"/>
            </ddd:ChartPlotter.MainHorizontalAxis>
            
        </ddd:ChartPlotter>

 

Really easy and strightforward. Notice than choosing the candlestick theme does not involve changing a style, bust just setting a brush.  The green line shown one interesting trick, by specifying the WidthSpring, we spring all the chart with the left part aligned. Very important since we need to compare the charts all together. Frankly speaking I did not manage any way to achieve that with WPF Toolkit charts.

imageWidthSpring keeps the left part of the chart aligned.

Bar chart is done by specializing the PointsGraphBase chart. Data are passed as a regular LineChart:

 

public EnumerableDataSource<string[]> VolumeDS
        {
            get
            {
                return volumeDS;
            }
            set
            {
                value.SetXMapping(k => DateTime.ParseExact(k[0], "yyyy-MM-dd", CultureInfo.InvariantCulture).Ticks);
                value.SetYMapping(k => double.Parse(k[5], CultureInfo.InvariantCulture));
                volumeDS = value;
            }
        }

 

An interesting part is what we show as labels on the XAxis ? We can customize that too:

<ddd:NumericAxis LabelProvider="{StaticResource tickToDate}"/>

As we can see, we provide as LabelProvider that produce the label for each tick. If we are not satidfied by the tick, we can provide our TickProvider.

Here below you can find my DynamicDataDisplay version ( sorry for providing that way, I’m tryng to contact the development team to send the patches )

and here the sample app:

Sunday, 15 May 2011 20:31:57 (GMT Daylight Time, UTC+01:00)  #    Comments [1] - Trackback
Charting | D3 | WPF

# Monday, 09 May 2011

 

As you can see in this discussion, it is not possible to pass a “dotted” expression in an ActionMessage parameter with CM. This is due to the fact that supporting this in a complete and consistent way will force caliburn micro to grow over the micro size. Let’s have a concrete example: we want to invoke an action on the StrokeCollected event of an InkCanvas, and we want to pass the Stroke property of the EventArgs.Here below the wanted syntax:

 <InkCanvas>
        <i:Interaction.Triggers>
            <i:EventTrigger  EventName="StrokeCollected">
                <cl:ActionMessage  MethodName="StrokeCollected" >
                    <cl:Parameter Value="$eventArgs.Stroke">
                        
                    </cl:Parameter>
                </cl:ActionMessage>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </InkCanvas>

 

If we use the standard behavior, only the $eventArgs portion of the expression is resolved, adding the dot forces CM to just emit the whole string as a parameter. Since we can deal in an application with a simplified strategy, that not necessary cover all scenarios, but is good enough for our purpose, we can redefine the MessageBinder.EvaluateParameter strategy:

var microEvaluator = MessageBinder.EvaluateParameter;
           MessageBinder.EvaluateParameter = (s, t, c) => 
           {
               string[] dotted = s.Split('.');
               if (dotted.Length == 1)
               {
                   // use default CM strategy
                   return microEvaluator(s, t, c);
               }
               else
               {
                   // let's CM happy with any type
                   var first = microEvaluator(dotted[0], typeof(object), c);
                   var dw = Dig(first,dotted.Skip(1));
                   return dw;
               }
                
           };

 

As you can see, we leverage the inner evaluator in the case we have a non dotted separated argument, or for the first chunk of the expression if the dot exists. The Dig function, by the old plain reflection work recursively to return the proper value:

 

        private object Dig(object first, IEnumerable<string> iEnumerable)
        {
            if (iEnumerable.Count() == 0)
                return first;
            else
            {
                PropertyInfo pi = first.GetType().GetProperty(iEnumerable.First());
                if( null == pi )
                {
                    Exception e = new Exception("Property not found:"+iEnumerable.First());
                    LogManager.GetLog(GetType()).Error(e);
                    throw e;
                }
                return Dig(pi.GetValue(first, null),iEnumerable.Skip(1));
            }
        }
As you can see it is pretty simple, despites some fault intolerance, that we can accept since this code will not be part of the library, but is under our control.
Monday, 09 May 2011 21:43:04 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Caliburn | WPF

# 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

# Monday, 21 March 2011

This is an example on implementing a behavior for zooming a 2D representations in WPF in a CAD friendly fashion, in the sense we need some facilities to have the same line thickness at different zoom level as well as text size. This because in 2D cad application we usually need to zoom into details but line thickness are actually zero width lines so they must not appear thicker as we look near to them, and even text sometimes need the same strategy. The same as we zoom “far” from the drawing, line thickness should appear the same. In this sample we focalize just a first zoom mode, the one handling the mouse wheel, that is simple because it does not require much user interaction handling ( in comparison to a “zoom redct” function ), but as in a real 2D cad application, we want a real zoom at point.

We implement this function as a behavior, so zooming seems “a thing attached” in XAML. An attached behavior, in WPF term is, as a per John Gossman definition:

The Attached Behavior pattern encapsulates "behavior" (usually user interactivity) into a class outside the visual heirarchy and allows it to be applied to a visual element by setting an attached property and hooking various events on the visual element.

Designing a behavior can start by the XAML, so we start by writing the XAML we expect to use in the way we like, as for example:

<Canvas z:Zoomable.Mode="Wheel" Background="White" SnapsToDevicePixels="True" x:Name="topCanvas">

 

The intent of this XAML is ( hopefully ) clear: we want to handle the zoom functionality on the Canvas in the mode “Wheel”. The underlined portion show where we attach the behavior. I did underline the Background assignment too: this is not exactly related to this behavior, but in general to get the canvas firing the mouse wheel events ( and any other mouse events ) it is necessary to specify a non transparent background, and these events are necessary to our behavior to work.

Implementing a behavior is done by using an attached property, and binding to the UIElement that property is applied to an event handler. In our implementation we use a class called ZoomHandler to handle the events:

public static readonly DependencyProperty ModeProperty =
           DependencyProperty.RegisterAttached("Mode", typeof(ZoomMode)
, typeof(Zoomable)
, new UIPropertyMetadata(ZoomMode.Disabled, new PropertyChangedCallback(OnModeChanged)));

       protected static void OnModeChanged(DependencyObject depo, DependencyPropertyChangedEventArgs depa)
       {
           Panel panel = depo as Panel;
           
           if (null == panel)
               throw new Exception("ZoomBehavior can only be attached to  objects derived from Panel");
           if (!attachedHandlers.ContainsKey(panel))
           {
               attachedHandlers[panel] = new ZoomHandler(panel);
           }
           attachedHandlers[panel].SetMode((ZoomMode)depa.NewValue);
       }

We attach a ZoomHandler class instance for each panel we want to zoom-enable, and we keep collected these object in an internal list. We define another attached property called UnityThickness. This is an important property in implementing CAD like behaviors: it is bound to the value of thickness of a line that appear to be one pixel thick at the selected zoom level. This property value is valuated from the ZoomHandler class, at the same time we apply the scaling factor, here below the function:

void canvas_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
       {
           if (currentMode == ZoomMode.Wheel || currentMode == ZoomMode.WheelAndMouse)
           {
               var reference = panel.Parent as IInputElement;
               if (null == reference)
                   reference = panel;
               Point pt = e.MouseDevice.GetPosition(reference);
               Transform mt = panel.RenderTransform;
               Matrix m = mt.Value;
               double amount = 1.0 + Math.Sign(e.Delta) * .1;
              
               m.ScaleAt(amount, amount, pt.X, pt.Y);
               currentAmount = m.M11;
               panel.RenderTransform= new MatrixTransform(m);
               Zoomable.SetUnityThickness(panel, 1.0 / currentAmount);
           }
       }

This function is the real one doing the zoom work. A scaling matrix is computed, to scale at an origin point defined by the current mouse coordinates. Then the attached UnityThickness property is set on the panel this ZoomHandler is handling. The scale amount is extracted form the first diagonal value of the RenderMatrix, by doing this we suppose we are using uniform scaling in zoom. Since we probably need to draw geometry with different thickness, we need some helper to bound the UnityThickness with different factors. The same can be done for font sizes. In order to achieve this, an helper class called ScaledThicknessSource is created: whith this class we can provide a scaled thickness by the current scale factor, here we can write:

  <Canvas z:Zoomable.Mode="Wheel" Background="White" SnapsToDevicePixels="True" x:Name="topCanvas">
            <z:ScaledThicknessSource  Thickness="1.0"  x:Name="Thickness1" UnityThickness="{Binding Path=(z:Zoomable.UnityThickness), RelativeSource={RelativeSource AncestorType=Canvas}}"  />
            <z:ScaledThicknessSource  Thickness="3.0"  x:Name="Thickness3" UnityThickness="{Binding Path=(z:Zoomable.UnityThickness), RelativeSource={RelativeSource AncestorType=Canvas}}"  />
            <z:ScaledThicknessSource   Thickness="22.0"  x:Name="FontSize12" UnityThickness="{Binding Path=(z:Zoomable.UnityThickness), RelativeSource={RelativeSource AncestorType=Canvas}}"  />
            <TextBlock Canvas.Left="20"  Canvas.Top="40" Foreground="Goldenrod" FontSize="{Binding Path=ActualThickness,ElementName=FontSize12}" >Non scaling text</TextBlock>
            <TextBlock Canvas.Left="240"  Canvas.Top="40" Foreground="Goldenrod" FontSize="22" >Scaling text</TextBlock>
            <Rectangle Fill="RosyBrown" StrokeThickness="2" Canvas.Left="60" Canvas.Top="80" Stroke="DeepSkyBlue" Width="100" Height="100"/>
            <Ellipse Fill="Brown" StrokeThickness="{Binding Path=ActualThickness,ElementName=Thickness1}" Canvas.Left="160" Canvas.Top="80" Stroke="Blue" Width="100" Height="100"/>
            <Path Canvas.Left="20" Canvas.Top="200" Stroke="BurlyWood" Data="M 45,0 L 35,30 L 0,30 L 30,55 L 20,85 L 45,60 L 70,85 L 60,55 L 90,30 L 55,30 L 45,0"/>
            <Path Canvas.Left="120" StrokeThickness="{Binding Path=ActualThickness,ElementName=Thickness3}" Canvas.Top="200" Stroke="DarkCyan" Data="M 45,0 L 35,30 L 0,30 L 30,55 L 20,85 L 45,60 L 70,85 L 60,55 L 90,30 L 55,30 L 45,0"/>
            <Image Canvas.Left="280" Canvas.Top="80" Source="/Assets/leo-mini.png" Width="128" Height="128"></Image>
        </Canvas>

In the example above, we create some instances of ScaledThickessSource, and we bound the property UnityThickess to the UnityThickness of the Zoomable behavior. Please note the syntax used:the () is necessary for an attached property. The thickness value is the desired one, at any zoom level. Then the examples geometry and text are bound tho the ActualThickness property of the helper instance, in order to have the proper scaled value.

Now we can look some examples of the behavior at work:

image The canvas with some example element. A test mantaining the dimension at any zoom level, a text affected by the zoom. The square has a standard thick border, the circle a correted thick border. The left star is with a standard border, and the rightr one has a fix tick border of two pixel. The image is added to show the zoom behavior working on raster images too.
image Here we show how the test is kept at each zoom level.
image Zooming in. The circle border thickness is kept, the square not.
image The same for the star. Notice as the left one appear to be bigger when we zoom in, this is because the left star border is not scaled.
image Zoom in works on Raster images…
image And zoom out too.

Another little thing, even if not necessary, the anti aliasing effect can blur a little the lines drawing, we can disable it in the following way:

 <Canvas z:Zoomable.Mode="Wheel" Background="White" SnapsToDevicePixels="True" x:Name="topCanvas">

Panning is not implemented yet. I would probably enable the ScrollViewer able to handle the pan, at present a standard ScrollViewer does simply not work since canvas does not measures the contained children total occupied size.

Monday, 21 March 2011 21:01:30 (GMT Standard Time, UTC+00:00)  #    Comments [3] - Trackback
Programmin | WPF

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 2017
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 124
This blog visits
All Content © 2017, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano