Wednesday, 26 November 2008

In my previous post, I introduced my thoughts on how animation between positions should be done. Today I will walk you through some of the technical benefits of that approach with a cool animated wrappanel sample. Yes, the silverlight control toolkit includes a wrappanel. Let’s animate it, the easy way!

Sample

I got some feedback that the samples that I inlined were not visible from rss feeds. So, visit this page to see the sample in action.

image

Please note the big black slider on the right.. Drag it to the left to do some layout transitions between items.
Also, to illustrate the flexibility of this approach, there is a textbox on the top that determines the startdelay of the items (Random between 0 and the number you give it). Set it to 700 milliseconds and then quickly drag the slider to the left. You will see some items moving immediately, others moving after some time. This gives it a less ‘plastic-fantastic’ feel.

The items are shown on the page using the xaml below. Notice how I use a regular wrappanel as ItemsPanelTemplate.

        <ItemsControl Grid.Row="1" x:Name="anim" HorizontalAlignment="Left">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ItemMovementSpike:MoveableItem Margin="10">
                        <Border Background="Yellow" Width="80" Height="80" >
                            <ContentPresenter Content="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ItemMovementSpike:MoveableItem>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Controls:WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemsSource>
                <Controls:ObjectCollection>
                    <System:String>1</System:String>
                    <System:String>2</System:String>
                    <System:String>3</System:String>
                    <System:String>4</System:String>
                    <System:String>5</System:String>
                    <System:String>6</System:String>
                    <System:String>7</System:String>
                    <System:String>8</System:String>
                    <System:String>9</System:String>
                    <System:String>10</System:String>
                    <System:String>11</System:String>
                    <System:String>12</System:String>
                    <System:String>13</System:String>
                    <System:String>14</System:String>
                </Controls:ObjectCollection>
            </ItemsControl.ItemsSource>
</ItemsControl>

 

Again: who does the animation? Panel or the item

One of the first samples on layout transitions inside a panel are from Dave Relyea (DevDave) and can be seen here. The big difference between the approaches is that he uses a custom-made wrappanel, which does the layout transition.

As you can remember from my previous post, I believe that a panel should only calculate and determine the actual logical position of an item. The transition between positions is not the concern of the panel and should be handled by some other dedicated object. In this case, you can see that I’ve chosen to wrap my content inside of a ‘MoveableItem’ whose concern it is to transition between positions.

As discussed, it is a pity that we have to work so hard inside of MoveableItem, because panels do not notify their children about a position change. But it can be done fairly efficient.

C’mon, isn’t the panel responsible for layout.. So it is HIS concern!

No sir, I strongly disagree. The panel is responsible for the layout of an element on the screen, sure. But they exist in all kinds of forms (Grid, dockpanel, wrappanel) and the intent is to determine the end position as quickly as possible. I feel it is not okay to start mixing that concern with an animation framework.
As always, a class should have only 1 reason to change. A panel should only be changed to alter the layout logic, not because we decided to add features to our transitioning logic.

What are the benefits of separating these concerns

By letting a panel be a panel, and having another class handle the transition, you get a much cleaner model.
First and foremost, we now do not have to alter panels in order to use animation. Most of the solutions I have seen require you to change the baseclass of your panel. This means you can not easily leverage the panels that someone else created, like the toolkits WrapPanel or DockPanel or the build-in Grid and StackPanel! It would mean creating your own versions of these panels. If you’re on the Silverlight side, you may copy our source and change the baseclass, but that will be pretty hard to do for a Grid in any case.

Second, designtime experience. Although I setup my animation in code at this moment, MoveableItem could also just go to a different visual state: ‘Moved’ and allow you to use Blend to create a transition yourself! This would be very easy to do, because MoveableItem could just expose a double where 1 means: in endposition and 0 means: in beginposition. That double could be easily animated using keysplines to create cool effects. See my expander series for more on that approach. I might follow up with a complete sample.

Stretching it a bit, I feel these come into play as well:

Flexibility. I can think of quite a few interesting properties I might want to set on my ‘MoveableItem’, like Weight, Gravity and so on. We could plugin Penner-equations (like, easeIn, bounce etc.) at the item level in a very clean way (cleaner than attached properties).

Performance. The effects I am thinking of go beyond mere transitions. For instance, it might take one item some time to ‘settle-in’: slowly rocking for some time before it finally goes silent. Others might have settled earlier. A panel keeps performing arrange overrides to allow for this. This is overkill.

Conclusion

I find this an intriguing topic. I know people have been using transitioning panels for quite some time now and are very comfortable with it. I hope that this post does make you think though, even though you might completely disagree :)
Let me know either way!

Wednesday, 26 November 2008 21:08:01 (Romance Standard Time, UTC+01:00)  #    Comments [8]  |  Trackback
 Sunday, 23 November 2008

In my previous post, we talked about one approach to visualize the change of content. So, we had a control with the content ‘Ruurd’ and when we changed the content to ‘RJ’, we could very easily setup a fade out for ‘Ruurd’ and a fade in for ‘RJ’. Or get more fancy and add a small translate transform.
In this post I want to share some of my thinking on a related subject: how do you visualize the movement of an object? For example: we have a button in a grid on column 0 and we move it to column 1. That move is instant, but in many cases you would like an actual animation between those locations.

There is precedence here, namely in the many tweening libraries for Flash and nowadays for Silverlight. Also, Nikhil has written a lot about this subject with his great attached behavior series.

Sample

I like typing in that textbox a LOT. I’m sure you will too.  :)

Power to the item or does the panel still rule?

It is hard to determine when you should use a panel to do animation and when you should not. I live by this rule:

When the movement itself has meaning, use a panel. If it is an effect, let the item take care of it.

This means: if during the movement you should be able to stop the movement and use the items in that position, than the visual tree should not have any translate transforms going on. The layout system should be managing the location of these items.
If on the other hand the movement is just a transition, the panel should not need to be aware of this transition and just be used to determine the logical positions of an item. That is many times more efficient.

To use examples: a carousel is showing items and we let the user ‘nudge’ the items a few pixels –> the new positions are the real positions and thus a panel should be used.
Items in a dockpanel or a stackpanel that move around within that panel should be managing their transition themselves.

So, I believe effects (visual position) should be managed by the item, logical position should be determined by the panel.

This has the added technical advantage that we do not have to rewrite all panels. This is illustrated by the xaml for this sample:

    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ItemMovementSpike:MoveableItem HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >
            <Button Click="Button_Click" Content="Move me" />
        </ItemMovementSpike:MoveableItem>
        <ItemMovementSpike:MoveableItem Grid.Row="1" HorizontalContentAlignment="Stretch" >
            <TextBox TextChanged="TextBox_TextChanged" Text="TypeMe" />
        </ItemMovementSpike:MoveableItem>
</Grid>
You can see I just use the regular Grid layout panel, nothing to see there!
Efficient location determination

Because we do not want to change our panels, we will have to determine our position on the screen ourselves. This is a somewhat inefficient process, so it is important to start thinking about where we want to take that hit.

The WPF/Silverlight layout system is very cautious about forcing a layout pass in a panel. It only does so when it is forced, so you can be certain that something has changed. The part of the layout pass that we are interested in is the Arrange part. During the arrange, the panel asks each child to arrange itself given a certain Size and then determines its position. So:

Panel.Arrange
  for each item: Item.Arrange
Panel –> set location and size for item (using a rectangle)

During this time, the most beloved of events is fired continuously on the item: CompositionTarget.Rendering.

The Rending event is called each time before the item is drawn on the screen and therefore comes with great power! If we were to do anything that is using cpu-cycles in this event, we will see some serious performance problems in our application. So, we need to be clever about it.

It is important to know that during the Item.Arrange, our item is still in its old location: The panel has not yet set its position, that will come a few Rendering events later. So, we can use the Item.Arrange to determine the current position with a TransformToVisual call. This is an expensive call, but since we only use it in the Arrange method (which is called only when necessary), it is cheap enough for our purposes.

   78 protected override Size ArrangeOverride(Size finalSize)

   79 {

   80     fromLocation = TransformToVisual(((UIElement) this.Parent)).Transform(new Point(0, 0));

   81     fromLocation.X += tt.X;

   82     moved = true;

   83     return base.ArrangeOverride(finalSize);

   84 }

I determine the current location on line 80 as it relates to its parent (the panel). You could do a quick visual tree walk to find our plugin root, which would enable some cool scenarios!!

Line 81 corrects for our current translatetransform (tt) and then we set a boolean ‘moved’ to true, indicating that something has happened.

The important stuff happens in our Rendering event:

   55 void CompositionTarget_Rendering(object sender, EventArgs e)

   56 {

   57     if(moved)

   58     {

   59         moved = false;

   60         toLocation = TransformToVisual(((UIElement) this.Parent)).Transform(new Point(0, 0));

   61         startmove = DateTime.Now;

   62         moving = true;

   63     }

   64 

   65     if(moving)

   66     {

   67         double fraction = DateTime.Now.Subtract(startmove).TotalMilliseconds/200d;

   68         tt.X = (fromLocation.X - toLocation.X)*(1 - fraction);

   69 

   70         if(fraction >= 1)

   71         {

   72             moving = false;

   73             tt.X = 0;

   74         }

   75     }

   76 }

It happens to be that in the first rendering event that is called, the move has occured. I’m not sure if that is a general rule, or something that just happens consistently on my machine. I haven’t looked into that yet.

We do one more inefficient TransformToVisual to find out where we currently are. Then we need the current time (startMove) and we indicate that we are moving. In the moving code we set the appropriate translateTransform (tt) and make sure that we stop moving when time is up.
If you’re into penner equations, you would plug them in after line 68.

No source for this one though, it’s just a spike. There are many things yet to be considered. But do let me know your thoughts.

Sunday, 23 November 2008 01:58:52 (Romance Standard Time, UTC+01:00)  #    Comments [15]  |  Trackback
 Thursday, 20 November 2008

This post will show you how to write a very simple contentControl, that allows you to transition your old content with your new content. It is a little prototype I put together after wanting to ‘spice up’ another control I was working on!

Show me!

What?

A contentControl is a control that only has one reason in life: to show your content. You will use it in places where you have an arbitrary object that you wish to display. For instance, a ‘Person’ business object, or a ‘string’. Its two most useful properties are ‘Content’ and ‘ContentTemplate’. The latter will let you define how to show your person.

By bundling two contentControls, we can move the new content to the upper contentControl and show the old content in the lower contentControl. Then we can use blend to think up some great transition between those visuals.

Why?

The current contentControl does not allow you to do a transition effect because it has no concept of ‘old content’. This means the change can not be visualized in a rich manner. The only thing you could do is transition in the new content, but the old content will be gone instantly.

Why not?

So, the Silverlight team could have just build such an approach into the framework, why didn’t they? Well, I have not checked officially, but can come up with a bunch of reasons. Most of all, this will keep a reference to old content (for the time the storyboard runs) that you might not expect. Not a big deal on a string, but possibly a very big deal on a large business object. Also, using this approach will result in a much larger object graph inside of the visual tree than just a contentControl: we’re adding a second contentControl, a layout panel, two visualstates and a few storyboards. Finally, creation of a template is costly and now happens twice when the content gets changed.
So, it is not a good idea to use this control all over the place. Please use sparingly, with caution and very lightweight templates.

How?

It’s a pretty straightforward control. (I’ll not do the pictures thing this time.. let’s see how copying regular code feels!)

    9     [TemplateVisualState(Name = "Transitioning", GroupName = "PresentationStates")]

   10     [TemplateVisualState(Name = "Normal", GroupName = "PresentationStates")]

   11     [TemplatePart(Name = "PreviousContentPresentationSite", Type = typeof(ContentControl))]

   12     public class TransitioningControl : ContentControl

   13     {

   14         private ContentControl PreviousPresentationSite { get; set; }

   15 

   16         public TransitioningControl()

   17         {

   18             DefaultStyleKey = typeof(TransitioningControl);

   19         }

Like I said, we’ll need a second contentControl to host our old content. This is represented by line 11.

Pretty interesting is the onApplyTemplate:

   21         public override void OnApplyTemplate()

   22         {

   23             base.OnApplyTemplate();

   24 

   25             PreviousPresentationSite = GetTemplateChild("PreviousContentPresentationSite") as ContentControl;

   26 

   27             Panel root = GetTemplateChild("LayoutRoot") as Panel;

   28 

   29             Storyboard sb= null;

   30 

   31             if (root != null)

   32             {

   33                 sb =

   34                     (from stategroup in (VisualStateManager.GetVisualStateGroups(root) as Collection<VisualStateGroup>)

   35                      where stategroup.Name == "PresentationStates"

   36                      from state in (stategroup.States as Collection<VisualState>)

   37                      where state.Name == "Transitioning"

   38                      select state.Storyboard).FirstOrDefault();

   39             }

   40 

   41             if (sb != null)

   42             {

   43                 sb.Completed += ((sender, e) =>

   44                                      {

   45                                          // go to normal state and release our hold on the old content.

   46                                          VisualStateManager.GoToState(this, "Normal", false);

   47                                          if (PreviousPresentationSite != null)

   48                                          {

   49                                              PreviousPresentationSite.Content = null;

   50                                          }

   51                                      });

   52             }

   53 

   54             VisualStateManager.GoToState(this, "Normal", false);

   55         }

I’m looking for the Transitioning State and take its StoryBoard. Now I can register some code to execute when the storyboard finishes. This represents our ‘cleanup’.
Obviously, this is prototyping code, so do not just copy this and use in a production system! At the very least you would need to take care of unhooking the event, etc. etc.

   57         protected override void OnContentChanged(object oldContent, object newContent)

   58         {

   59             if (PreviousPresentationSite != null)

   60             {

   61                 PreviousPresentationSite.Content = oldContent;

   62 

   63                 base.OnContentChanged(oldContent, newContent);

   64 

   65                 // if busy with transitioning, let's skip to normal

   66                 VisualStateManager.GoToState(this, "Normal", false);

   67                 // and start our state

   68                 VisualStateManager.GoToState(this, "Transitioning", true);

   69             }

   70         }

So, when our content changes, we get a very convenient ‘old content’ object.

I just quickly change to Normal state, which probably already happened (line 46), but if the content changes again before the storyboard finishes, it looks better to start afresh.

This is my attempt at a transition:

                        <vsm:VisualStateManager.VisualStateGroups>
                            <vsm:VisualStateGroup x:Name="PresentationStates">
                                <vsm:VisualState x:Name="Transitioning">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CurrentContentPresentationSite" 
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="-40"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.800" Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CurrentContentPresentationSite" 
Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.800" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" 
Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.800" Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" 
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.800" Value="40"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Normal">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" 
Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

 

This is how the sample is setup:

        <local:TransitioningControl x:Name="contentChanger" 
                                    HorizontalAlignment="Center" 
                                    VerticalAlignment="Center" 
                                    Content="{Binding Path=CurrentTime}">
            <local:TransitioningControl.ContentTemplate>
                <DataTemplate>
                    <Border BorderBrush="Blue" BorderThickness="2">
                        <ContentPresenter Content="{Binding}" />
                    </Border>
                </DataTemplate>
            </local:TransitioningControl.ContentTemplate>
</local:TransitioningControl>

CurrentTime is a string that changes each second. The datatemplate is not necessary at all, just showing that it works.

I’d appreciate some feedback on this. So let me know if you would find such a control useful.

Source

Thursday, 20 November 2008 01:40:00 (Romance Standard Time, UTC+01:00)  #    Comments [42]  |  Trackback
 Monday, 17 November 2008

In my previous post, I showed an approach to getting the expander to ‘reveal’ its content. Although it worked well, it did so by programmatically creating a storyboard and targeting the height/width. That did not sit well with me, and in this post I’ll show another approach.

Before I had settled on that approach, I had created a dependency property on Expander ‘ExpandAmount’ but quickly realized I could not target it from within the template. Since you also can not target custom attached properties in a storyboard, I was stuck. However, the solution is as clear as it is simple: Just create a custom ContentControl that has our beloved ‘ExpandAmount’ property. We will be able to target that property for sure!

The template becomes:

image

Note that I set the Height and Width to 0, because the expander always begins in ‘collapsed’ state. Visibility is not set to collapsed.
We can target it in our –now Blend friendly- VSM:

image

The relevant code on our ExpandableContentControl is shown here:

image

Since content can be either a UIElement or a regular object (like String), we can not use it to determine the size we would like to be. However, we can take a look at the contentpresenter that is presenting our content and ask it. By doing this in the OnApplyTemplate, we will not be able to respond to changes inside the contenttemplate. However, for our demonstration, that is not a big issue.

One issue I ran into was the fact that this control has no nice way to get to the expander and find out how it should do calculate its Size. Based on the ExpandDirection, we might want to change the width or the height. I chose to have the Expander tell its content when it starts to expand or collapse.

We end up with a fully customizable expander. Go have some fun in Blend. Below is a sample where I adjusted the speed to slow down at the end. Also included is the source.

 

Source

Monday, 17 November 2008 20:42:24 (Romance Standard Time, UTC+01:00)  #    Comments [23]  |  Trackback
 Sunday, 19 October 2008

I’m very excited that Silverlight 2 has been released. I’m too new to Microsoft to claim even the slightest involvement, but it’s wonderful to see the excitement both within Microsoft as outside.
It will be interesting to see what will happen with the (already great) uptake of Silverlight by the market.

As I am spending most of my days knee-deep in Xaml nowadays, I always try to find things that will help me be more productive. It happens quite often that I want to select a complete xaml tag. It’s way too much effort to use the mouse to select it, so I often use the control-m-m shortcut to collapse a tag and then select it. However, a few days ago I took 5 minutes to automate this.

image

When you put your mouse somewhere in the Grid tag, and use my macro, you end up with this:

image

You can even put your mouse in the endtag. I bound it to Control-Q and it has made my life that much better!

The macro is as simple as this:

    Sub SelectXMLTagContents()
        DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstColumn)
        DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
        DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstColumn)
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
End Sub

It collapses a tag, jumps to the first column, selects the line and then does an uncollapse.

For those using a tool like Karl’s ‘Xaml Power Toys’, it might also be a worthwile addition to their shortcuts.

Sunday, 19 October 2008 21:17:36 (Romance Standard Time, UTC+01:00)  #    Comments [26]  |  Trackback
 Friday, 25 July 2008

Josh Smith just published a great article about his solution to using RoutedCommands in WPF.

The problem he solves, has been solved by others before, however, I think this is a very lightweight succinct way of doing it.
Basically, when you set a command to a button, you will have to handle that logic (canExecute and Execute) in the codebehind of the view. Since you are (hopefully) using a MVC, MVP or MVVM approach, you would rather not go through the codebehind of the view, but directly route the commands to the appropriate viewmodel/controller.

He creates a relaying object that does just that. This results in a completely empty codebehind for the view, which is exactly what I like!

Good job Josh!

Friday, 25 July 2008 09:17:02 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
 Wednesday, 16 April 2008

I just finished a small sample application that illustrates a client/server application using Entity Framework on the server and just regular objects on the client. The client has custom changetracking and the server is able to attach the graph to a context again. Source can be found at the efcontrib page, and I guess I'm almost ready to do a proper release!

[I used Prism to build the client in a Model View Controller approach. It was a fun exercise and I'm looking forward to seeing that project released.]

The application manages employees and allows for setting a 'teamleader' on an employee: think of 'is managed by'. I thought it would be cool to send that over the wire.

Here is a screenshot of the main view of the application:

image

As you can see, you can 'choose' an employee. When you press that button, you will see another screen where you can enter a lastname. It will fill a grid with employees matching that criteria and allows you to choose from that list.
It is also allowed to 'add an employee'. There are actually 3 types of employees you can add: Mort, Elvis and Einstein.

On the row of teamleader, you can again press the 'choose' button, which will allow you to set a relation between the employee you are editing and another employee.

On the server, there are a few methods like this:

  0   public List<Employee> GetEmployees(string lastNameBeginsWith)
  1   {
  2    using (InheritanceTypeContext context = new InheritanceTypeContext())
  3    {
  4
  5     List<Employee> employees = (from e in context.Person.OfType<Employee>().Include("TeamLeader").Include("TeamMembers")
  6       where e.Lastname.StartsWith(lastNameBeginsWith)
  7       select e).ToList();
  8
  9    
  10     employees.ForEach(p => context.PrepareForSerialization(p)) ;
  11     return employees;
  12    }
  13   }
  14

 

You can see me taking care to call the 'prepareForSerialization' on each graph that I'm returning on line 10.

The client can just use these objects like normal.

 

I'll look into delving into it a bit with a screencast soon.

Wednesday, 16 April 2008 14:55:10 (Romance Standard Time, UTC+01:00)  #    Comments [6]  |  Trackback
 Tuesday, 15 April 2008

I'm building a small sample for EFContrib, and thought it would be cool to use the new MVC framework 'Prism' for it. Prism is a new framework currently under development by the patterns and practices group. It is not feature complete and everything might change in the next drop. But, well, it's fun to see such a framework develop and how best to understand it, than by building something simple with it!

I'm trying to do something fairly basic: I have a view that has a button on it. If the button is pressed, a form should popup where we can search for employees. When the search is over, the result should be accessible by my controller.
At the same time though, I know that I'm going to have a detail screen as well with the same button on it. Here the button chooses a teamleader for the employee.

I want to define the command once, but need my controllers to behave differently. It's quite possible that I would be better off just creating two commands (one for the detail screen and one for the employee screen). You could argue that they perform different actions: choose an employee versus choose a teamleader.
But I don't swing that way and I feel it should be possible to have the same command on a lot of buttons and let the appropriate controller deal with it.

In the prism project are a few base classes for commands: the DelegateCommand and also the ActiveAwareDispatchCommand. As far as I can see, they allow a command to be hooked up by multiple views and allow controller to register their interest in them.
I created a static class with my 'ChooseEmployee' command:

 

    public static class EmployeeChooserCommands
    {
        public static ActiveAwareMultiDispatchCommand ChooseEmployee = new ActiveAwareMultiDispatchCommand();
      }

Now, my views couple their buttons to this command in the regular way.

In my definition of MVC a controller is responsible for the logic and thus handles this command.

        protected ActiveAwareDelegateCommand chooseEmployeeCommand;

It defines it's own command and in the ctor hooks it up:

            chooseEmployeeCommand = new ActiveAwareDelegateCommand(Choose, CanChoose);
            // register this instance on the global
            EmployeeChooserCommands.ChooseEmployee.RegisterCommand(chooseEmployeeCommand);

The last line will make this controller react to executions of the command by every source.

This is the pattern that I see in the current Prism reference implementation project.

The fun thing about the ActiveAwareDelegate is the way you can set it as Active and not-Active. If it is not active, it will not be queried for canExecute information and its execute delegate will not be called.

So, what I did, was to let my views implement the IActiveAware interface and throw an event when they lose or get focus. The corresponding controllers react to it in this way:

        void view_IsActiveChanged(object sender, EventArgs e)
        {
            chooseEmployeeCommand.IsActive = view.IsActive;
          }

Setting the command to only be active when the view is active.
Downside here is that if one view is active, it gets to decide on the canExecute result, but all buttons in all views will react to it: clearly not what we want.

So, I feel I'm on the wrong track here. I really miss being able to set some sort of 'affinity' to the RegisterCommand method. I would like to let that method know I'm interested in commands where the source is equal to my view. But then again, maybe I should just create different commands :-)

Tuesday, 15 April 2008 17:50:12 (Romance Standard Time, UTC+01:00)  #    Comments [14]  |  Trackback
 Thursday, 28 February 2008

After writing so much about my own MVC implementation for WPF, I'm happy to see the birth of Prism. This is what the site has to say about it:

"Prism" addresses the challenges around building complex enterprise WPF applications. As the complexity increases and the teams grow, the application becomes increasingly difficult to maintain. Using "Prism" enables designing a composite application that is composed of many discrete, loosely coupled modules. These modules can be developed, tested and deployed by separate teams.
It provides the following benefits:

  • Provides complete support for WPF
  • Dynamically composes user interface components
  • Application modules are developed, tested and deployed by separate teams
  • Allows incremental adoption
  • Provides an integrated user experience

"Prism" is not a port of previous smart client offerings, instead it is a new deliverable that is optimzed for WPF. It aims to deliver a simplified approach that is more easily adoptable.

Very exciting!! Although I ofcourse will be disappointed if there is not a good way to integrate WF into it.

Thursday, 28 February 2008 18:03:16 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

Finally wrapping up.

This is the seventh of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

Recap

In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
In the previous post we looked at injecting objects and retrieving.

Broadcasting

CAB (and other systems) uses an event aggregator to publish events. Subscribers (other controllers) can subscribe to a specific 'topic' using a string to identify it. This works well, but does mean yet another communication method is introduced.

Since every workflow/controller is added to the workflow runtime, we could easily ask for all the loaded workflows and send these a message. However, since all adapters subscribe to a weakevent manager to manage communication, I thought I'd stick to this pattern.

The BroadcastCommandMessage was created for the adapter to react on and check if it's controller is interested in it. If it is, the message is transformed to a command message and send to the controller.

I have not yet build an activity to do this.
The Bankteller sample has a CustomerQueueController. When it gets focus or loses focus, it wants to tell 'someone' (just someone who will listen) that it has a popular command to (un)register. The BanktellerLogic controller will use this information to put the command in a list and the view decides to make a menu item for it. You see, I do not believe that the CustomerQueueController should be able to decide that a menu is to be created out of it. He just wants to let the world know about a command.

        private void RegisterCommands(object sender, EventArgs e)
        {
            commandSvc.SendBroadcast(
                new BroadcastCommandMessage(this.WorkflowInstanceId, "RegisterPopularCommand",
                   CustomerQueueInteractions.AcceptNextCustomerFromQueue));
        }
        private void UnRegisterCommands(object sender, EventArgs e)
        {
            commandSvc.SendBroadcast(
                new BroadcastCommandMessage(this.WorkflowInstanceId, "UnRegisterPopularCommand",
                   CustomerQueueInteractions.AcceptNextCustomerFromQueue));
         }

 

That concludes this series for now.

I hope you enjoyed it. I hope you take away the feeling that it is pretty easy to build a MVC system using WPF and WF and that the presented solution is about as decoupled as it gets.

Thursday, 28 February 2008 02:16:34 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Tuesday, 26 February 2008

Hole crap, this is starting to be a long series!!

This is the seventh of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

Recap

In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
In the previous post, we talked about injecting controllers to manage specific parts of your screen, very cab-alike.

IOC - Inversion of Control

Inversion of Control is a pattern that tries to turn everything upside down when it comes to getting to dependencies. Let's say you have a class, and to do its work it needs a helperclass (maybe a communication service). Instead of having your class create that service explicitly, we can have your class just ask for it and have someone else supply it. This is where Dependency Injection comes from: just state what a class needs to work and have a container 'inject' those dependencies.
Doing it this way makes for a more maintainable application and allows you to better manage the lifetime of helperclasses and services. You might want to get back the same service instance, all the time!

Using a MVC approach to construct your application, you might feel the same need. Maybe you are building an application that allows editing of pieces of information of a customer, for instance, her details, her address, etc.
These pieces are implemented in different views. All the views that belong to that one customer, should use the same instance of the 'customer' object.

Inject and retrieve object into resources - activity

In this system, that is easily done, although possibly more explicitly than many great IOC containers (Windsor, Spring.Net, StructureMap) would like it.

Just have one controller create the object and inject it inside of his resources. Because of the way retrieving resources work, all the controllers that live 'below' this controller (are nested within it), will be able to retrieve it.

image

Here I have dragged in the 'InjectObjectAsResource'Activity, and have bound a public field on my workflow to the 'Service' property of the activity. Well, maybe Service is a bad name, but I just expect you to use it with services most of the time. Also, the activity might better have been called InjectInstanceAsResource, but I guess I didn't.
I used a type as resourcekey this time, instead of a string.

I bet you can figure out how the retrieve activity works ;-)

Tip: since the activity does not know what type of object you want to create, if you let the binding introduce the field or property to your code, it will be typed as object. Just change that to your own type.

The retrieve will work for all controllers that can reach the resource dictionary of the controller that did the inserting. So, that is equivalent to the CAB-term: 'child workitem'.
If you have the need to also be able to share on a global level, just make the inserting happen on the application resources, instead of the adapter resources. Can not be too hard.

Conclusion

I think this mechanism illustrates the way you can use WPF to meet most of your CAB needs. I use it here from a workflow, but that has nothing to do with the core-concept.
I find that the explicit visual call to inject or retrieve, without having to write code to do so, could be beneficial when building systems in a team. There is no need to guess where an object comes from, it is all very much in your face.

Tuesday, 26 February 2008 13:00:22 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Monday, 25 February 2008

This is the sixth of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

Recap

In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
In the previous post, we talked about decoupling through commands.

This time, we will look at how to inject a controller into a subview

The InjectControllerAsDataTemplate activity

It's all very nice and dandy to have one controller manage it's mainview, but what happens if part of that mainview is different, and should be managed by a completely different controller?

Let's look at ModuleView in the BankTeller sample:

<UserControl x:Class="BankTellerViews.ModuleView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <StackPanel Orientation="Horizontal">
        <StackPanel Orientation="Vertical">
            <ContentPresenter ContentTemplate="{DynamicResource userinfo}" />
            <ContentPresenter ContentTemplate="{DynamicResource customerlist}"/>
        </StackPanel>
        <StackPanel Orientation="Vertical">
            <ContentPresenter ContentTemplate="{DynamicResource customerinfo}" />
            <ContentPresenter ContentTemplate="{DynamicResource customersummary}" />
        </StackPanel>
    </StackPanel>
</UserControl>

You can see that ModuleView really only determines the way this screen is build up, but the individual pieces are left empty.

When we open up the ModuleLogic controller, we wish to inject controllers with the same names that we used here:

image

What happens exactly? Well, you selected a controller type, through the convenient typebrowser, and set a specific resource key (in this case, we used a string: userinfo). The adapter is notified by this adapter to do something with it. It will create a datatemplate in code, and just set it as a resource (or replace, if it already exists).

This means that a deeply nested view could easily define a contentpresenter and a higher level controller could inject a controller for it.

Monday, 25 February 2008 16:12:47 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

This is the fifth of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see

    Whoops, I guess I was a bit over enthusiastic in the previous post, because I already explained the hooking mechanism in enough detail.

    It boils down to registering the adapter as global commandhandlers and when a command reaches it, create a commandMessage and send that to the workflow.

  • Monday, 25 February 2008 15:58:49 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Friday, 22 February 2008

    I sometimes do it, but don't like to do it too often. But this one, I just want to archive here so I can always find it: Beatriz has just released a great ready-to-use drag and drop library. She has also written a terrific blog post about it here, that shows the steps she took to achieve it.

    I just ran the project and it performs well, has insertion adorners and even allows dragging and dropping within the same list. Good stuff!

    Friday, 22 February 2008 13:54:19 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

    This is the fourth of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see
    Recap

    In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
    The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
    In the previous post, I talked about the various ways to show a view, and actually already talked about the decoupling mechanism: commands.

  • I'm very lucky to have received some good comments from Wekemf about tight coupling. I urge you to read those comments and maybe chime in.

    In this post I will not return on that subject, but will quickly address two important activities that help in configuring your system quickly: the SetMainContent activity and the SetDataContext activity and sending WPF commands to WF's HandleCommand.

    SetMainContent activity

    A controller adapter is a normal WPF contentcontrol. It has the job to participate in the visual tree on behalf of our workflow controller class. To actually attach a view to it, we need to set it's content property.

    As shown in the previous post, you can just set on in xaml yourself, but it's more logical to let the workflow decide on the view. Ofcourse, the best approach is totally up to you.

    I usually use the stateinitalization activity to set up a view for us. I drag in the SetMainContent activity, and choose a type from the references assemblies.
    If it weren't for this step, the controller assembly would not need a reference to the view assembly at all. I found it very cool to be able to select a type with the typebrowser and just have it show up.

    The typebrowser is located in an assembly I have put in the externalAssemblies folder. It is a project, not started by me. The code did not work when I got my hands on it, but I managed to fix it by using a hammer. Check out this post to learn more about this great design-time experience!

    If you have a business need to decouple even further, you would need to adjust the SetMainContent activity, and instead of sending a real Type, send a string key or whatever. Then you would create some mapping functionality to map that key to the actual view.

    When the adapter get's notified by the SetMainContentMessage that it needs to set a content, it will just create the view (using reflection) and place it as it's own content.

    SetDataContext activity

    I do not like MVP at all, where the presenter talks back to the view directly (using an interface or something). I feel it's way too 'pushy' and way too much work. I believe in databinding (especially WPF bindings, I think Microsoft got it right this time). You view should just bind to your domain objects. In many cases, it's better to create a wrapper for the domainobjects, so you have the opportunity to supply some shortcut properties or view specific stuff: you might have a list of products, and you want the view to display the sum of the prices. That is a great opportunity for the viewmodel to expose a 'Sum' property that the view can simply bind to.

    The object that is used as a ViewModel should live with the controller who will be able to communicate with it.
    I usually create an internal public class, simply called ViewModel and have the controller inject that class with domain objects.

    The Set DataContext activity is very similar to the SetMainContent activity, in that it let's the adapter know it has to set a datacontext on itself.
    You configure the SetDataContext activity simply by choosing a field or property of your controller.

    In small sample applications, I have used the 'invoking' event, to hook up some code that actually initializes the ViewModel object.

    Sending WPF commands to the Workflow: HandleCommandActivity

    The HandleCommandActivity is really what makes using the solution so easy. I have blogged about it already extensively, and I will just summarize here:

    Workflow has a difficult communication story. You need to define your incoming and outgoing calls in an ExternalDataExchangeService. Then you have to hook up events in your workflow to listen to incoming calls/events. It is not possible to listen to the same events in two different states, without using the very difficult CorrelationTechnique.

    This is not necessary for our usage. I have created the HandleCommand activity to just listen to a queue with a specific name. That name is defined by the command we are listening to. So, if you want your workflow to react when you send it the string 'workflowRules', you would just drag in the HandleCommand and configure the Command property to read 'workflowRules'. No need to setup a special event for it.

    The commandService class has a PostCommand method, that you can call to put a message on the queue. That's all there is to it.

    So, when we receive a WPF command, we cast it to a RoutedUI command. The commandname is used to form a SimpleCommandMessage which can be used as input to the PostCommand method.

      1         #region command sinks
      2         private void CmdExecuted(object sender, ExecutedRoutedEventArgs e)
      3         {
      4             string commandname = (e.Command as RoutedUICommand).Name;
      5
      6             PostCommand(commandname, e.Parameter);
      7
      8         }
      9
    10         private void PostCommand(string commandname, object Parameter)
    11         {
    12             if (implementedCommands.Contains(commandname))
    13             {
    14                 commandSvc.PostCommand(new SimpleCommandMessage(instance.InstanceId, commandname, Parameter));
    15             }
    16         }
    17
    18         private void CmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
    19         {
    20             string commandName = (e.Command as RoutedUICommand).Name;
    21
    22             if (implementedCommands.Contains(commandName))
    23             {
    24                 e.CanExecute = commandSvc.CanExecute(new SimpleCommandMessage(instance.InstanceId, commandName));
    25             }
    26         }
    27
    28         #endregion

    As you can see, I first check if the workflow even implements such a command. If not, it would be too expensive to send it to the workflow.
    Also, check out the CmdCanExecute method. It actually makes it possible for the workflow to put rules on the HandleCommand activity that are used to figure out if a command can be executed. For instance, if you are not authorized to do something, the command was never in CanExecute, so the button that hooks up to it was always dimmed!

    I hope that clears up some questions. Let me know what you think!

    Friday, 22 February 2008 11:24:20 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Thursday, 21 February 2008

    This is the third of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see
  • Recap

    In the first post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
    The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.
    In the previous post, I showed a wizard style application.

    This post follows Part II, starting the application and the adapter. In that post we started our shell and explained how the adapter communicates with a workflow instance, how it can react to commands (normal RoutedUI events from wpf controls) and react to events by the command service.

    We will now continue, by looking at a simple view.

    View responsibility

    Let's first look at how we perceive a view in the MVC paradigm.
    A view should be nothing more than the visualization of your data. The only authority it has, is the authority to decide how to represent a piece of data on the screen. That means it should not contain any business logic. Be very strict about this: the responsibility of a view is the visualization of data.

    So, let's take a look at a common scenario where these lines may blur.
    Take a list of products and let's say that if we have a new product-line that has been introduced within the past month, we want to use another background color, to alert our customers to this new hot product.

    We could solve this in our binding perhaps (let's just assume that is easy), but we should not do that. That would mean the view is deciding when a product is new and hot. It should not.
    The only thing the view should do is create the two visual representations of products and use a datatemplate selector to decide which is hot or not. The datatemplate selector could be injected by our controller. Another way to solve this, is for the controller to put this information in the ViewModel itself. Like, add a boolean 'new' which the view uses.

    If you do not do it this way, and you are embedding logic inside of your view, you will quickly end up with scattered logic, never knowing where something is defined. Changing rules becomes hard and your application will break at some point.
    Now, I understand, and have done many times, that sometimes you just do not have the time to do it right. But always remember that in the long run, you will get burned. Try to setup a situation where it is easy to do the right thing, by making it easy to use datatemplate selectors or use the viewmodel.

    View decoupling

    MVC advocates not letting your view have any knowledge whatsoever of the controller. It does this, because tight coupling of the view to the controller will destroy maintainability and flexibility. If you tight couple, you are unable to swap controllers or views. Most importantly, if you couple the view to the controller (by making it call specific methods on the controller), it becomes harder to maintain/refactor.

    There are certainly approaches that do couple view to controller. If you look at the very powerful Caliburn framework, you will see that the framework has 'action messages' that directly call methods on the controller. I have yet to work with that extensively, so I can not be sure, but it feels to me there should be a very explicit layer between view and controller, which defines how the view will communicate with the controller.

    Our goals in this project are to use the tools WPF provides us to communicate with the rest of the system. We do so with Commands.
    A command can be seen as a message that is passed upward (and downward) the visual tree. Since our adapter lives just above the view and is part of the visual tree, it will have the opportunity to react to the command.

    When building a view, you should also explicitly define all the interactions that view expects to have with the outside world. Do that in a static class like so:

        public static class ImportantWizardInteractions
        {
            public static readonly RoutedUICommand Next;
            public static readonly RoutedUICommand Back;

            public static readonly RoutedUICommand GotoClientScreen;
            public static readonly RoutedUICommand GotoAdresScreen;
            public static readonly RoutedUICommand GotoRoleScreen;
            public static readonly RoutedUICommand GotoCarScreen;

            public static readonly RoutedUICommand Save;
            public static readonly RoutedUICommand SaveYes;
            public static readonly RoutedUICommand SaveNo;


            static ImportantWizardInteractions()
            {
                Next = new RoutedUICommand("Next", "Next", typeof(ImportantWizardInteractions));
                Back = new RoutedUICommand("Back", "Back", typeof(ImportantWizardInteractions));

                GotoClientScreen = new RoutedUICommand("GotoClientScreen", "GotoClientScreen", typeof(ImportantWizardInteractions));
                GotoAdresScreen = new RoutedUICommand("GotoAdresScreen", "GotoAdresScreen", typeof(ImportantWizardInteractions));
                GotoRoleScreen = new RoutedUICommand("GotoRoleScreen", "GotoRoleScreen", typeof(ImportantWizardInteractions));
                GotoCarScreen = new RoutedUICommand("GotoCarScreen", "GotoCarScreen", typeof(ImportantWizardInteractions));

                Save = new RoutedUICommand("Save", "Save", typeof(ImportantWizardInteractions));
                SaveYes = new RoutedUICommand("SaveYes", "SaveYes", typeof(ImportantWizardInteractions));
                SaveNo = new RoutedUICommand("SaveNo", "SaveNo", typeof(ImportantWizardInteractions));


            }
        }

    By being explicit about your interactions like this, you will be able to unit test more easily as well.

    Use in your view like this:

    <Button Command="{x:Static local:ImportantWizardInteractions.GotoClientScreen}">Client</Button>

    A command is great for buttons and other stuff, but how do you do for instance communicate that a customer was selected from a listview?

    1. well, you bind to a selectedCustomer property hopefully, and when the customer was selected, that property changed on the viewmodel. The controller might pick that up.
    2. More explicitly though: do use the SelectedItemChanged event and use the codebehind of your view as a translation layer to talk to the outside world:
    3.         private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
              {
                  // send a command
                  CustomerQueueInteractions.SelectNewCustomer.Execute(e.AddedItems, this);
              }

    You can call me on that. It's not a very elegant solution. I'd rather be able to do away with the codebehind of a view entirely. But using the codebehind is actually fine: it is part of the view, and it should not be allowed to do anything else than to act as a translator for view specific things to commands.

    So, how to show a view

    Well, building a view is nothing else than just deriving from usercontrol and doing your thing. Using commands and going wild on the visuals. (try to animate everything!!! your client loves it).

    It depends now how you want to show it.

    1. Let's say your building a project where you don't care about fancy composition and pluggable modules in your application, and you just want your shell to show your view. The shell might have the following code:
      <c:GenericWorkflowAdapter WorkflowController="{x:Type logic:AControllerForYourView}" >
         
      <v:YourView/>
      </c:GenericWorkflowAdapter>

      I am assuming you do want a controller around your view.

      Here a controller is instantiated and it's content is set to your view. Easy.
    2. Let's say we want our controller to choose what view it uses. That seems to me to be the nicest way to go about it. We will again put a controller in the visual tree, but will not set a view already:

      1. <c:GenericWorkflowAdapter WorkflowController="{x:Type logic:ImportantClientWizard}" />

      Then, in the workflow, we might use some fancy logic to determine which view we will show (perhaps looking at the role of the user). To actually set a view, we will use the SetMainContentActivity. Drag that to the canvas and select a type.

      image

      Selecting a type is easy, because of the typebrowser I included:
      image 

    3. Yet another way, that is suitable for 'subviews', is to define a contentpresenter on some view anywhere:
    4. <ContentPresenter 
      ContentTemplate="{DynamicResource CurrentWizardScreen}" />


    And use the InjectViewAsDataTemplate activity in a controller to place a contenttemplate in the resources section with the same resourcekey.
    image

     

    I'll follow up with another take on decoupling the view from the controller, by looking at the SetDataContext activity and talking a bit more about the viewmodel.

    Thursday, 21 February 2008 11:57:02 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
     Wednesday, 20 February 2008

    Scott Guthry announces the .Net 3.5 client product Roadmap here.

    Highlights are improved bootstrapping of 3.5 for your client applications and improved cold startup times.

    But the real news for the WPF addicts: the dropshadow and blur bitmap effects will now be hardware accelerated!! That is a big thing. These effects are completely useless at the moment, but if they are hardware accelerated, you will be able to do some great stuff. He also hints at a new effects API and data virtualization support.

    On top of that, he announces that there is a real DataGrid control coming, and my personal favorite: a Calendar/Datepicker control.

    I can easily live without a datagrid, these are so easy to create with the listview, that I don't see a reason to actually build a new control. However, the lack of an official datepicker is in-excusable for enterprise applications. I'm happy to see they are working on it!

    Wednesday, 20 February 2008 12:16:33 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

    This is an intermezzo from the MVC with WF series. I have added a new sample to the project, which I hope demonstrates the flexibility of using WF.

    The rest of this series can be found here:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see

    It is a simple 4 screen 'wizard' where logic determines that it should skip one screen. Also, when the save button is hit, a popup will show that asks if you are sure. If you are, you will be sent to the first screen, otherwise you will return to your last screen. It has buttons on the left that determine where you can go, as well as 'next' and 'previous' buttons.
    All of this was done with a minimum of code and a maximum of dragging and dropping activities. The whole reason for doing this, is that when you now get a new feature request ("We have a new screen that sits in between the client and adres screen!!!"), using WF it will be dead-simple to add it.

    I have uploaded the executable here, just in case you don't feel like opening up the project and building yourself.
    The application looks like this:

    image

    And when you reach the 'Car' screen, it will look like this:

    image

    Hitting the Save button here:

    image

    A few things to notice about this sample:

    • There are 2 controllers doing their job here:
      • The usersettings controller, with a view on top. It allows you to check a checkbox. Doing so makes you an administrator. Notice how, when you do so, you are able to browse to the 'Role' screen. You see, if you are not an administrator, you are not allowed to enter the role screen.
      • The 'ImportantWizardController', which handles the mainview. It shows a few buttons (Client, Adres, Role and Car) on the left, which will allow you to go to the screens you have already passed. It also shows a previous and next screen button. Finally, it defines a contentpresenter where our subviews will be injected.
    • The buttons react immediately. Go to the Car screen, and then check your checkbox to make yourself Administrator. This means you have the right to visit the Role screen, and it immediately pops up.
    • No code behind. Nowhere. The only codebehind is on the ImportantWizardControl to 'load data' (actually returning an empty client, but you get the drift).
      It felt really cool to build this plumbing without coding.

    Let's look at the steps to produce this application:

    1. I added a Controller project (type workflow), a Domain project (with a few very simple classes), a shell project that will be used to start us up and a view project which holds the views we are going to use:
      image
    2. I created a ClientService and a UserService class which will be classes used by our workflows:
          [Serializable]
          public class UserService
          {
              public bool IsAdministrator { get; set; }

          }
          [Serializable]
          public class ClientService
          {
              public Client CurrentClient { get; set; }

          }
    3. Then the shell was used to inject our main view and also inject a global userservice class:

        1 <Window x:Class="EditLogicShell.Window1"
        2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        4     xmlns:logic="clr-namespace:EditLogicControllers;assembly=EditLogicControllers"      
        5     xmlns:c="clr-namespace:ControllersAdapters;assembly=ControllersAdapters"
        6     Title="Window1" Height="300" Width="300">
        7     <Window.Resources>
        8         <logic:UserService x:Key="globalUserService" />
        9     </Window.Resources>
       10     <StackPanel>
       11         <Border BorderThickness="1" BorderBrush="Black" Background="Beige">
       12             <c:GenericWorkflowAdapter WorkflowController="{x:Type logic:ManageUserSettingsController}" />
       13         </Border>
       14         
       15         <c:GenericWorkflowAdapter WorkflowController="{x:Type logic:ImportantClientWizard}" />
       16     </StackPanel>
       17 </Window>

      Note line 8, where we place a UserService instance in the resources section
      On Line 12 we start our UserSettings controller
      On Line 15, we start our main wizard.

    4. Let's not go into the usersettings controller. It's just too simple. It will inject a view, and set the datacontext to the userservice class. He retrieved that class using the 'RetrieveObjectFromResources' activity.

    5. I then asked our designer (yup, that was me too... could you tell??) to design our individual views. Everywhere the designer knew he had to interact with the system, a command was created in a static class. That class turned out to be like this:

          public static class ImportantWizardInteractions
          {
              public static readonly RoutedUICommand Next;
              public static readonly RoutedUICommand Back;

              public static readonly RoutedUICommand GotoClientScreen;
              public static readonly RoutedUICommand GotoAdresScreen;
              public static readonly RoutedUICommand GotoRoleScreen;
              public static readonly RoutedUICommand GotoCarScreen;

              public static readonly RoutedUICommand Save;
              public static readonly RoutedUICommand SaveYes;
              public static readonly RoutedUICommand SaveNo;


              static ImportantWizardInteractions()
              {
                  Next = new RoutedUICommand("Next", "Next", typeof(ImportantWizardInteractions));
                  Back = new RoutedUICommand("Back", "Back", typeof(ImportantWizardInteractions));

                  GotoClientScreen = new RoutedUICommand("GotoClientScreen", "GotoClientScreen", typeof(ImportantWizardInteractions));
                  GotoAdresScreen = new RoutedUICommand("GotoAdresScreen", "GotoAdresScreen", typeof(ImportantWizardInteractions));
                  GotoRoleScreen = new RoutedUICommand("GotoRoleScreen", "GotoRoleScreen", typeof(ImportantWizardInteractions));
                  GotoCarScreen = new RoutedUICommand("GotoCarScreen", "GotoCarScreen", typeof(ImportantWizardInteractions));

                  Save = new RoutedUICommand("Save", "Save", typeof(ImportantWizardInteractions));
                  SaveYes = new RoutedUICommand("SaveYes", "SaveYes", typeof(ImportantWizardInteractions));
                  SaveNo = new RoutedUICommand("SaveNo", "SaveNo", typeof(ImportantWizardInteractions));


              }
          }
      And on individual screens, the commands were used like this:
                  <Border Background="Beige" BorderThickness="1" BorderBrush="Black" DockPanel.Dock="Left" Width="120" >
                      <ListView>
                          <Label FontWeight="Bold">Previous screens</Label>
                          <Button Command="{x:Static local:ImportantWizardInteractions.GotoClientScreen}">Client</Button>
                          <Button Command="{x:Static local:ImportantWizardInteractions.GotoAdresScreen}">Adres</Button>
                          <Button Command="{x:Static local:ImportantWizardInteractions.GotoRoleScreen}">Role</Button>
                          <Button Command="{x:Static local:ImportantWizardInteractions.GotoCarScreen}">Car</Button>
                      </ListView>
                  </Border>
      (This is the list of buttons that are shown on the left hand side of the screen)
    6. The views were passed to the developer (guess who) and the following state machine was created:
      image 

      Obviously a thing of beauty.

      1. The state initialization will retrieve the userservice, load data, set our maincontent to the mainView and set our next state to clientDetails

      2. The clientdetail has an initialization as well: it will set the datacontext to our customer and inject the ClientView as a datatemplate. Then it waits for only one command: Next. If that is triggered, it will simply move to the AdresDetails State.
        When moving out of a state, the state finalization is triggered, which will remove the view from the resources.
        Note how great it is never to have to think about that cleanup code again, it is always executed when moving out of a state.

      3. The adresDetails state has a few more commands it will listen to. When moving 'Next', a piece of logic is executed:
        image
        There is a declerative rule in the IF/ELSE that goes a little something like this: this.GlobalUserService.IsAdministrator == True
        That rule is automatically put in the rules repository and can be used by others. It determines if the next screen will be the Role screen or the CarDetails screen.

      4. Role is simple.

      5. CarDetails also reacts to the Save-command. When it get's triggered, it will inject our popup into the resources section, and move on to the save state.

      6. The Save state will react to 'SaveYes' and 'SaveNo'. It will remove the popup from the resources, and go to another state.

    7. The views are dead simple, just binding to properties. However, the ImportantWizardMainView does require our attention. It has this definition for our subview:

                  <!-- our subview, uses name: CurrentWizardScreen -->
                  <ContentPresenter 
                  Content="{Binding RelativeSource={RelativeSource FindAncestor, 
                  AncestorType={x:Type local:ImportantWizardMainView}, AncestorLevel=1}, Path=DataContext}" 
                  ContentTemplate="{DynamicResource CurrentWizardScreen}" />


      Apparently, when using the contentTemplate, the datacontext is not inherited. So I have to set it up to react to the changing datacontext of our main screen. So, when the DataContext of ImportantWizardMainView is changed, the Content of our presenter is changed to match it. (Leave comment on how I could do this simpler, if you know how).

    8. Also interesting is that I used a Grid on that view, with two children that overlay eachother. The other child is our popup screen:

              <!-- our popup lives on top of that -->
              <ContentPresenter ContentTemplate="{DynamicResource PopupScreen}" />

      When we set a datatemplate with name Popupscreen, it will be shown on top of our regular screen. I like it!

    I have added a new activity, InjectViewAsDataTemplate. We already had the InjectControllerAsDataTemplate, but there are times you don't want a whole controller.

    I've replaced the original project file with the most recent. It can be found here.
    If you are interested in seeing more about this subject, please leave a short comment!

    kick it on DotNetKicks.com

  • Wednesday, 20 February 2008 11:55:27 (Romance Standard Time, UTC+01:00)  #    Comments [18]  |  Trackback
     Tuesday, 19 February 2008

    This is the second of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

  • Workflow as controller: Introducing <M,V,C> where M: ViewModel, V : WPF, C : WF
  • Part II, starting the application, and the adapter
  • Intermezzo: new sample application
  • Part III, your first view
  • Part IV, decoupling view from controller
  • Part V, marshalling commands from WPF to WF
  • Part VI, Injecting a controller in a subview / workspace
  • Part VII, IOC on the cheap: injecting and retrieving objects
  • Part VIII, Broadcasting for all to see
  • I thought it best to just put out that TOC, to force myself to actually write these short posts ;-)

    Recap

    In the previous post, the complete solution was presented. I am presenting a solution to use workflow as the controller part in your MVC inspired WPF application. It is inspired on the thought that you do not need complex frameworks, because WPF already gives you great power (routed eventing, resources). So, no IOC is used, no event aggregator etcetera: it's taken care of by WPF and WF, a natural fit.
    The solution is very decoupled and I feel it's a great advantage to be able to visual your control logic.

    Starting the application / Shell

    The term 'Shell' is used to indicate a startable 'host' for your application. In WPF, that is probably your App.xaml view. In there, you point to a startupUri of a window. We do not need anything different for our application, but we do need to start the workflow runtime.

    I have chosen not to build a generic application.start method, because I am still thinking about threading. For now, I have chosen to use the ManualWorkflowSchedulerService to let the workflow instances do it's thing. Normally the workflow runtime uses a workerthread to execute the workflow instances on the background. That means that when you send a command to the workflow, it will be run in the background. That sounds great, but will give you some pain when changing data that is bound to the UI thread. For this first version, I did not want that pain, so I used the ManualWorkerThreadScheduler. Now, the workflow instance will do nothing, until we explicitly donate our (UI)thread to it.

    Starting the runtime is simple:

      1         public App()
      2         {
      3             // start a workflow runtime
      4             workflowRuntime = new WorkflowRuntime();
      5
      6             ManualWorkflowSchedulerService manualSvc = new ManualWorkflowSchedulerService(false);
      7             workflowRuntime.AddService(manualSvc);
      8
      9             ExternalDataExchangeService dataSvc = new ExternalDataExchangeService();
    10             workflowRuntime.AddService(dataSvc);
    11             dataSvc.AddService(new CommandService(workflowRuntime));    // add our generic communication service
    12
    13
    14
    15             workflowRuntime.StartRuntime();
    16             workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(workflowRuntime_WorkflowTerminated);
    17             workflowRuntime.WorkflowAborted += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowAborted);
    18             workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
    19
    20
    21             ControllersAdapters.WorkflowRuntimeHolder.SetCurrentRuntime(workflowRuntime);
    22
    23             this.Exit += new ExitEventHandler(App_Exit);
    24         }

    At line 7, the ManualWorkflowSchedulerService is indeed added to the runtime.
    At line 11, our own communicaton class (CommandService) is added to the runtime. You can interpret the runtime as a global object container: when we ever want to use that commandService singleton, we can just ask the runtime for it.
    Lines 15 through 18 hookup some eventhandlers to certain events. We'll cover them next.
    Line 21 sets this runtime at a static propery for the controllerAdapters to fetch. A quick and dirty solution.

    The events that we subscribe to are handled as follows:

      1         void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
      2         {
      3             ICommandService cmdsvc = workflowRuntime.GetService(typeof(ICommandService)) as ICommandService;
      4
      5             cmdsvc.SendMessage(new InstanceWasRemovedMessage(e.WorkflowInstance.InstanceId));
      6         }
      7
      8         void workflowRuntime_WorkflowAborted(object sender, WorkflowEventArgs e)
      9         {
    10             ICommandService cmdsvc = workflowRuntime.GetService(typeof(ICommandService)) as ICommandService;
    11
    12             cmdsvc.SendMessage(new InstanceWasRemovedMessage(e.WorkflowInstance.InstanceId));
    13         }
    14
    15         void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
    16         {
    17             ICommandService cmdsvc = workflowRuntime.GetService(typeof(ICommandService)) as ICommandService;
    18
    19             cmdsvc.SendMessage(new InstanceWasRemovedMessage(e.WorkflowInstance.InstanceId));
    20         }
    21
    22         void App_Exit(object sender, ExitEventArgs e)
    23         {
    24             workflowRuntime.StopRuntime();
    25         }

    As you can see, I fetch the command service from the runtime, and ask it to send a message. The commandservice will 'broadcast' this message to all living controller adapters. When a workflow is finished, either by termination or just because it finished it's process, we need to let the adapter know so that it can unsubscribe from events from the commandservice.

    The adapter

    The GenericWorkflowAdapter is a WPF control that handles the communication between WPF and WF. We will see pieces of it in the upcoming posts, but we'll need to go into a little more detail here.

        /// <summary>
        /// This is a WPF type that can be placed anywhere in your UI tree. It can be configured with a workflow type.
        /// When it is, it will instantiate the Workflow.
        /// This adapter will then be able to pick up WPF Command (RoutedUI) and send them to the workflow, as well
        /// as listen to events coming from the runtime, the commandsvc and the workflow instance
        /// </summary>
        public class GenericWorkflowAdapter : ContentControl, IWeakEventListener
        {
               ...
        }

    As you can see, it is a contentControl. The workflowcontroller is able to place an arbitrary view as it's content.
    It has one property: WorkflowControllerProperty, typeof(Type), which will fire off the SetWorkflowController method when it is set.

      1         private void SetWorkflowController(Type type)
      2         {
      3             // actually start the controller!
      4             instance = runtime.CreateWorkflow(type);
      5             instance.Start();
      6
      7             // allow it to do it's thing
      8             threadSvc.RunWorkflow(instance.InstanceId);
      9
    10             Debug.WriteLine(String.Format("Adapter has started workflow instance {0}, of type {1}", instance.InstanceId, type.ToString()));
    11
    12
    13             // we will filter commands to only manage commands that we have defined in our workflow
    14             // so we have to walk recursively through all activities
    15             IEnumerable<System.Workflow.ComponentModel.Activity> flattenedActivities =
    16                 (instance.GetWorkflowDefinition() as System.Workflow.ComponentModel.CompositeActivity).EnabledActivities.
    17                 SelectRecursiveSimple(activity => (activity is System.Workflow.ComponentModel.CompositeActivity) ?
    18                     ((System.Workflow.ComponentModel.CompositeActivity)activity).EnabledActivities :
    19                     new System.Collections.ObjectModel.ReadOnlyCollection<System.Workflow.ComponentModel.Activity>(new List<System.Workflow.ComponentModel.Activity>()))
    20             ;
    21
    22             // let's get the handlecommands
    23             var commands = flattenedActivities.Where(act => act is HandleCommand).Select(act => ((HandleCommand)act).CommandName)
    24             ;
    25
    26             implementedCommands = new ReadOnlyCollection<string>(commands.ToList());
    27
    28             SetupCommandSinks();
    29         }

    As you can see, this method actually goes into the workflowruntime and ask for it to spin up a workflowinstance. Then it donates it's thread to actually 'run' the instance. The workflow instance probably has initialization code attached to it. That code get's run at this point.

    At line 15, I use Linq to go through every activity that is defined in the workflow and look at the HandleCommand activities. These are activities that wait for a command and act upon it. I need to know which commands this workflow might respond to, so I create a readonly collection from this. Later, we will only let the adapter pass commands that are actually implemented by the workflow!

    At line 28, there is a call to setup the command sinks:

            private void SetupCommandSinks()
            {
                // set up command sinks
                CommandManager.AddExecutedHandler(this, CmdExecuted);
                CommandManager.AddCanExecuteHandler(this, CmdCanExecute);
            }

    Here you see the simple code that will register this contentcontrol to handle RoutedUICommands from WPF. As you can probably guess, when a command reaches these handlers, they will be filtered by the 'implementedCommands' collection we defined earlier on, and if they are implemented AND they are currently enabled, the command is posted to the workflow.

    I have setup two events: the lost and gotFocus events, to also send commands to the workflow. If the workflow chooses to do so, it can handle these. I use them to remove and add options to the menu shell.

    The last thing to cover, is the ReceiveWeakEvent method. This adapter will register itself at the commandService, and the commandService will subscribe the adapter to a few events. It uses weakevents to do so, so that the lifespan of this adapter is not tied into the commandService (which will live forever).
    There are a whole host of message that can be sent in the system, and the ReceiveWeakEventMethod will implement different behavior for all of them. It will look at at the arguments that were passed, and check for a specific type.

    (I might refactor that, to actually put the logic into the messages).

    That's it for now, in the next post we will actually get our hands dirty and put together our first application!

    Tuesday, 19 February 2008 11:36:14 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Monday, 18 February 2008

    In this post and a few upcoming posts, I would like to present a solution I have built using Workflow as the controller for your WPF applications. I wish I could call it a framework and think of a great name for it, but it does not aim to solve all your UI-building problems in one go. It does however offer a very easy way to build a loosely coupled application, driven by WF and could be used to build upon for your own solution.

    Table of contents

    This is the first of a series about using Workflow Foundation to control your UI Logic in a WPF application. The full table of contents:

    Inspiration

    Like I mentioned in a blog post here, Josh Smith writes about using MVC in a WPF application where he does not use a funky IOC-container to help him build a MVC architecture, but uses the WPF framework itself to accomplish most of it.
    This resonated with me, because I just left a project where the combination of WPF and CAB did not make good on all it's promises. The team sometimes felt the combination was overly complex.

    Also Jeremy Miller writes about implementing all of the different aspects of CAB yourself. While doing so, he reasons (my interpretation) that it's best to build the simplest solution that is a precise fit for your problem, instead of using all kinds of big-time frameworks that abstract away so much, that you start to feel constrained.

    A great little post by Rob Teixeira concludes that most frameworks are way too complex to really use.

    I have had a bit of experience using WF on the server side, but have always thought of WF to be an excellent fit for the UI as well. When building complex UI's I would like nothing better than to be able to invite a business analyst to sit next to me and just show him what will happen when a button is pushed.
    I have had a team build a large UI for a LOB application. Although at first glance it looked very simple, there is always going on much more than you expect. Having a visual representation of the flow of actions in your program, is a good thing.

    This project aims to provide the most straight forward easiest plumbing possible, to get the job done. It tries to be explicit and make it easy for you (the developer) to do the right thing. It hopes that the use of WF provides some sort of DSL-feel to your application.

    So, what does this mean

    First, what does the solution not do:

    • It is explicitly not an IOC based solution (but perhaps you don't need that)
    • It is not a complete eventing mechanism (although controllers are able to communicate just fine)
    • It is not a finished solution (I might have called it a framework then!)

    What it is, is this:

    • It is a suggestion for how you could very easily use workflows as a controller
    • It combines some fun tricks I've learned, that will facilitate us here
    • It uses the native power of WPF, so no learning of new concepts just because you have a ShinyNewFramework, if you understand WPF, you understand how to hook things up
    • It uses the native power of WF to create your controller logic, this translates into a very descriptive usecase with easy handoff between developers and opens up possibilities of just letting your business analysts create the first draft themselves! WF always feels like a cheap-ass DSL to me.
    • It is one adapter class, a couple of activities and a command service. Very easy to understand and adjust to fit your own needs
    • It facilitates loose coupling to the extend where your views and your controllers do not need references to eachother
    • It is message based
    • Excellent testability, because of loose coupling and messages.

     

    Show us the goods

    I have uploaded the goods zipped here.
    It needs .net framework 3.5.

    In the previous post, I explained how you could combine the controller and wpf in one project. It seems that this does not work as well as it should: sometimes I get build errors that aren't there. It's fine to have logic and views separate for the real sample, but the shell consists of two projects now as well, that may seem as a bit overkill.

    I only UnitTested one small view to show how you can go about testing bindings and test the controller separately. I use TypeMock for this, so you might need to unload that project. (I'm considering TypeMock, but it is pretty expensive for a one-man-shop).

    What's in it

    The real stuff is very small.

    • project ControllersAdapters, with only one file. It is a contentcontrol, which acts as an adapter to your controllers [8 kb dll]
    • project WorkflowCommunications, which has the service that we can use to translate in/out of the controller and 6 custom activities, that do specific things [27 kb dll]

    That is all you need.
    I have loosely implemented the BankTeller application from CAB, or rather the SmartClientContrib 1.1 WPF for CAB. I did not look too closely at their implementation details, just copied the xaml and the domain model and build a part of it myself. Just to discover what was needed to build a real application.

    image

    The sample consists of a Shell, Domain, Logic, Views and Test project. It demonstrates how one could go about building such an application. I will follow up with a more detailed look at it. Suffice it to say, implementing it was a breeze.

    The thing with the BankTeller application is, that the logic is too simple. So it mostly demonstrates hooking up views and datacontexts.

    Just to give you a quick glance at what logic in a workflow looks like:

    image

    (Here you see what will happen when a new customer is selected in the listview. It checks if the customer is not null, and then sets a customerinfo view and a customer summary view. If it was null, the views are removed from the visual tree.)

     

    Go into more detail, please

    Well, I will follow up with more posts, if there is an interest in it. This post has dragged on long enough, so I will keep it very short for now.

    The concepts are:

    1. Use WPF resources as an excellent container for objects. Resource lookups work hierarchically, so it's actually pretty powerful on it's own. There are two activities Inject- and RetrieveObjectFromResource that will put or retrieve an arbitrary object into the resource section of the adapter. This could be a service or something else.
    2. Use WF as an event aggregator. All workflows are registered to the runtime, and all adapters subscribe (with weakevents) to the workflow. So it's easy to send messages around.
    3. Use WPF Commands to communicate from the View to the Controller. Commands go upstream. I have made it easy for a controller to handle a command (just drag a HandleCommand to the screen). I've also made it possible to use rules to determine if the command 'CanExecute'. So you could do a command 'AcceptCustomer' and bind it to a button. The Controller will determine if the command can be executed. (When the customerqueue is empty in the sample, the button to accept a customer is disabled automatically).
    4. Use WPF DataTemplates to inject UI by the Controller. The View can sprinkle ContentPresenters around (with ContentTemplates bound to DynamicResources). The controller will choose what piece of UI to inject as the resource. (cool stuff!)

    The most important class is the GenericWorkflowAdapter that can be placed into the UI like this:

    <c:GenericWorkflowAdapter WorkflowController="{x:Type l:ShellLogic}" />

    Here we tell it to use the workflowcontroller: ShellLogic as it's 'boss'.
    The adapter will hook into the RoutedUI commands coming from WPF and when a command comes that the workflow wants to react to, it will send it to the workflow. The workflow will react to it.

    Than, there is the CommandService, which defines the communication between the workflow and the runtime. The adapters use it to send messages to their workflow. The workflow uses it to communicate to the adapters.

    There are custom activities to do specific UI-things. Like setting a controller in the UI, or an object in the resources. Setting the datacontext of a view with your ViewModel and actually setting the Content of the adapter with it's View.

    More details will follow.

    Trixxxxxx

    In order to pull this off, a few things were hacked:

    • I created a much easier way to register commands on a workflow. Just drag a HandleCommand to an Eventdriven activity, set it's CommandName (the string it will react to) and you're off. Normal WF paradigm says you have to create an interface and possibly even implement correlation. Not productive for what we are trying to achieve.
    • Getting the workflow to communicate back to the adapter causes a clone to be made of the message. But since we don't want that, I implement IClonable to return 'this'. Works well, but you have been warned.
    • At one point I use a delegate that is passed to the workflow, that let's it get data from the commandService on the fly.
    • In order to use the custom activities, I needed to let the user (you) select types (what view you wish to inject, what controller you want to instantiate). I've had to jump through hoops to get it working. See this blog post.

    What is next

    I've had great fun implementing this. After a few refactorings, it turned out to be extremely simple. I'm interested in seeing what you think. If there is some interest from the community, it could easily be taken to the next level. However, at this point it was just a nice experiment for me. Let me know what you think of the idea!!

    kick it on DotNetKicks.com

    Monday, 18 February 2008 12:19:33 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
     Thursday, 14 February 2008

    Just ran into a little bug in Visual Studio/msbuild and could not find any answers in the forums, so I thought I'd put it up here for reference:

    When you want to use both workflow classes and wpf classes in one project, you will run into some strange behaviour. Let's do it together.
    If you want to skip the newbie stuff, jump to step 11 and see the bug.

    1. create a WPF project.
    2. unload the project and choose to edit the project file
    3. somewhere in the beginning of the file, you will find the following line:
      <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
      That is a way for visual studio to identify this as a WPF application project, and when you add an item, you will be able to choose a wpf item.
    4. You wish to be able to compile WF items, so add to the bottom of the file the correct import for the WF tasks:
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.Targets" />
    5. Note that WPF in the past needed the import of winfx, but with framework 3.5 you don't need that anymore!
    6. At this point you are able to copy a workflow or activity to your project and compile, but you want to be able to add WF items to your project, so scroll to the top of the file again.
    7. Add the Guid that identifies a WF project ({14822709-B5A1-4724-98CA-57A101D1B079};)  to your projecttypeguids tag. The complete tag should be on one line (!) and look like this:

      <ProjectTypeGuids>{14822709-B5A1-4724-98CA-57A101D1B079};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    8. Save the file and reload the project.
    9. Before adding a the first workflow to the project, first add references to System.Workflow.Runtime, Activities and Componentmodel.
    10. Add your first glorious workflow to the project.
    11. Be prepared to be disappointed: the project will not compile. Mine gave this error:

      Error    1    Error reading resource file 'j:\Users\Ruurd\Documents\Visual Studio 2008\Projects\WF_and_WPF_combined\WpfApplication1\obj\Debug\WpfApplication1.obj.Debug.WpfApplication1.g.resources' -- 'The system cannot find the file specified. '    J:\Users\Ruurd\Documents\Visual Studio 2008\Projects\WF_and_WPF_combined\WpfApplication1
    12. Notice the weird path of the resource file. It is looking for something with dots instead of path dividers. Strange.
      In regular windows explorer, go to the obj/Debug folder, and create a copy of the .g.resources file and use that weird name. I wanted to automate it though, so go to the properties of your project and use this as your pre-build script:
      IF EXIST "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).g.resources" (copy /-Y "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).g.resources" "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).obj.$(ConfigurationName).$(TargetName).g.resources") ELSE (echo "placeholder" > "$(ProjectDir)obj\$(ConfigurationName)\$(TargetName).obj.$(ConfigurationName).$(TargetName).g.resources")

      This checks to see if you already have a g.resources file and if so, copies it. Otherwise it will generate a placeholder file with the correct name. Atleast the project will build without problems.

    I have not tested it a lot yet. It seems to me that when the placeholder is created, there are resources that can not be found. During some quick and dirty tests, I've not had any problem yet and everything works just fine.

    Hope this helps someone out there.

    update: weird stuff. I have this running just fine in a couple of projects, but I have one project that gives an exception during a rebuild (not a build) in the compileworkflowtask. In other 'combined' projects, I can happily build and rebuild using the steps above.

    This is probably caused by wpf renaming the file to tmp_proj and the compileworkflow task is validating it's parameters like so:

            if ((string.Compare(this.ProjectExtension, ".csproj", StringComparison.OrdinalIgnoreCase) != 0) && (string.Compare(this.ProjectExtension, ".vbproj", StringComparison.OrdinalIgnoreCase) != 0))
            {
                base.Log.LogErrorFromResources("UnsupportedProjectType", new object[0]);
                return false;
            }

    The logging statement is the one giving the pain.

     

    Thursday, 14 February 2008 13:44:34 (Romance Standard Time, UTC+01:00)  #    Comments [9]  |  Trackback
     Wednesday, 13 February 2008

    I'm working on a sweet project at the moment using both WPF and WF. One of my custom activities has a property of type Type, where it would be cool for the user of the activity to be able to use the designer to select a type, just like what happens in the WF designer when I choose a type. However, no type picker popped up.

    So I went googling and found that Daniel Cazzulino also ran into this problem and created a fantastic little project to harness the power of the real WF typebrowser. He writes about it on this blogpost and later moves the project to code project. You can find the article and his download code here.

    However, as you can read in the comments, something was broken. Looking through the code, although small, made me not want to waste time on understanding the System.ComponentModel namespace in that much detail at this point ;-) (although, when working with WF, you will soon need to customize property pickers, so I will have to look into it someday soon).
    Daniel himself points to the Patterns and Practises entlib library: they offer the same functionality. I downloaded their sourcecode, and I'm quite sure they just used Daniels code and improved upon it a bit. However, with all the Entlib references, the project felt a bit heavy.

    What I have done is rip out all the references to entlib that I do not care about, used a few files from Daniels original solution and worked around a few shortcomings. Nothing fancy, I just hacked at it until it worked.

    image

     

    Now, since I have used some code (without license) by Daniel and code by the Entlib group, I'm not sure if I can publish a derivative without getting into problems. However, I've read their license, and I think it's okay.

    You can download the project here, don't ask for changes because I'm not interested in spending more time on it. All credits go to Daniel.

    (Also, find out how to create your own typefilters in his post).

    Have fun with it. Leave a comment if you find it useful.

    Wednesday, 13 February 2008 13:30:24 (Romance Standard Time, UTC+01:00)  #    Comments [9]  |  Trackback
     Tuesday, 12 February 2008

    It frequently happens that you wish to enrich a valuetype with more data, most often the properties in your domainmodel. In this post I will present one way you could achieve that. But first, let's look at why you would want such a thing, then look at how you would go about this normally and finally look at another approach.

    Why metadata about a property

    Let's say you have a domainobject 'Person' like so:

        public class Person
        {
            public string Name { get; set; }
            public DateTime Birthday { get; set; }
        }

    When working with this object, you will set the property 'Name' and property 'Birthday', but while setting these, you have no clue about what really is allowed to go in there. Maybe Name can not accept numerics and in our domain, any Birthday before 1-1-1990 is not allowed. These validationrules are unknown until you actually validate the object, using your preferred mechanism. At that point, there might be an error collection that will state which properties are set to disallowed values. Maybe validation will occur on each change to the data.

    That's not really a problem for your businesslogic, but your UI might want to know about these validation rules beforehand! Maybe it could adjust to show a different textbox for 'Name', one which will not let you enter a number, for instance.
    Yes, sure you could have put that specialized textbox in there yourself, but that means you will have to adjust your UI views when businessrules change. I would much rather just place a generic control, bind it to my property and let it decide for itself how best to present the data:

    <MetaDataEditor Content="{Binding Path=Name}" />  <!-- this shows an alphanumerical textbox -->

    So, why metadata: it allows you to optimize beforehand and simplify your UI.

    Freaky
    Oh, or maybe you want to give a 'friendly name' to the property. That friendly name could be presented in the UI as the label or used in error messages.
    How do you go about this normally

    (and I say 'normally' not in a bad way, it might still be the best way, depending on your situation).

    You would define some interface:

        interface IMetadataProvider
        {
            Metadata GiveMetadataForProperty(string propertyName);
        }

    and implement that on Person. Now, when you want your metadata object, you just get to the object on which the property is defined, and ask for it. Easy.

    Metadata<T>

    What I do not like about an interface, is the fact that you have separated the metadata from the property itself. There now is a method in my domainobject that will take a string (ouch) and probably go through a long list of  'if(propertyName == "???")' or switch/case statements until it gets to the correct name and then create or return a metadata object. That's a great deal of hooking up you need to do, and when passing strings, your domainmodel just became less easy to refactor.
    When my magical MetaDataEditor needs the metadata, it will have to somehow find it by traversing from the bound property to it's parent and cast that to IMetadataProvider.

    Oh, bad boy, don't even think about using reflection to magically connect the passed string to a metadataobject!

    That is why I am experimenting with a little class, I like to call Metadata<T>.

        public class MetaData<T>
        {
            public T InnerValue { get; set; }
            .... goodness inside
        }

    This way, you need to define a property on your businessobject like so:

    private MetaData<string> name = new MetaData<string>();

    public MetaData<string> Name
    {
        get
        {
            return name;
        }
        set
        {
            name.InnerValue = value.InnerValue; 
        }
    }

    This way, you can rest assured the original metadata object is never discarded, but only the innervalue is changed.

    We could work with the property like so (p is an instance of Person):
    p.Name = new MetaData<string>("foo");

    That's not easy, but we can also say:
    p.Name.InnerValue = "foo";

    Better. We can do one better though, by creating a few implicit operators on the metadataobject:

    public static implicit operator T(MetaData<T> source)
    {
        return source.InnerValue;
    }

    public static implicit operator MetaData<T>(T source)
    {
        IMetaData md = source as IMetaData;
        if (md != null)
        {
            IConvertible convertible = md.InnerValue as IConvertible;
            if (convertible != null)
            {
                T converted = (T)convertible.ToType(typeof(T), null);
                return new MetaData<T> { InnerValue = converted };
            }

            throw new NotSupportedException();

        }
        else
        {
            return new MetaData<T> { InnerValue = source };
        }
    }

    This means, we can now use the property as follows:

    p.Name = "foo";

    The string "foo" can be translated to a MetaData<T> and that is going into the property-setter. Then, the setter will take the innervalue of that foo-metadataobject and use it to set it's own innervalue.

    string importantname = p.Name   will work too.

    One important note though: this might be misleading to your developers. They can not do p.Name.ToCharArray(), because p.Name really is not a string.
    Or p.Car.Color. You would have to do p.Car.InnerValue.Color.

    Now, whether you go with the implicit operators or not, you want to ease databinding especially. For that, a typeconverter can be used.

    A typeconverter can be attached to a class by the use of an attribute, like so: [TypeConverter( typeof(MetadataForDatabindingConverter))]

    The converter needs to inherit from TypeConverter. Let's implement one.

      1 public class MetadataForDatabindingConverter : TypeConverter
      2 {
      3     /// <summary>
      4     /// keep the real type of the metadata innervalue. Since we need it when we convert back to our metadata
      5     /// object.
      6     /// </summary>
      7     private Type databindingRealType;
      8
      9     public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    10     {
    11         if (sourceType.Equals(typeof(string)))
    12             return true;
    13         else
    14             return false;
    15     }
    16
    17     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    18     {
    19         if (destinationType.Equals(typeof(string)))
    20             return true;
    21         else
    22             return false;
    23     }
    24
    25     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    26     {
    27         // ugly but necessary: when databinding to a ui control, it's likely that you want to go to a string representation
    28         // when the ui control (textbox?) was changed, the incoming value is a string. I have not yet found a way to
    29         // find out what the target really wants (for instance an MD<int>).
    30         // This hack works fine
    31
    32
    33         Type realtype = value.GetType();
    34         if (databindingRealType != null)
    35             realtype = databindingRealType;
    36
    37 
    39         // or just do a switch on the type and create the correct type
    40         //if(value is string)
    41         //    return (IMetaData) new MD<String> { InnerValue = (string)value };
    42
    43         // because I don't feel like implementing the above statements.. bla!
    44         Type d1 = typeof(MetaData<>);
    45         Type constructed = d1.MakeGenericType(new Type[] { realtype });
    46         IMetaData instance = (IMetaData)Activator.CreateInstance(constructed);
    47
    48         TypeConverter converter = TypeDescriptor.GetConverter(realtype);
    49         converter.ConvertFrom(context, culture, value);
    50
    51         instance.InnerValue = converter.ConvertFrom(context, culture, value);
    52
    53         return instance;
    54     }
    55
    56     public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    57     {
    58         // so, this is a metadata object, and we are going to be converting the innervalue to a string (for textboxes etc).
    59
    60         IMetaData md = value as IMetaData;
    61         if (md != null)
    62         {
    63             databindingRealType = md.InnerType;
    64
    65             TypeConverter converter = TypeDescriptor.GetConverter(databindingRealType);
    66             if (converter.CanConvertTo(destinationType))
    67             {
    68                 return converter.ConvertTo(context, culture, md.InnerValue, destinationType);
    69             }
    70         }
    71
    72         throw new NotSupportedException(String.Format("Conversion of {0} to type {1} is not possible.",value.ToString(), destinationType.Name.ToString() ) );
    73     }
    74
    75     public MetadataForDatabindingConverter()
    76     {
    77
    78     }
    79
    80 }
     

    A typeconverter should override the CanConvertFrom/To methods to indicate if it is able to convert between certain types. Our UI will present data as strings (textbox), so I have opted to only convert to and from strings.

    Line 7 keeps a variable where the 'real type' will be put. The databinding engine does not give much information during the call to convert. So if we have a MetaData<int> and bind that to a textbox, the ConvertFrom only gives us information about the value being set (the string "1234"). How do we know we have to convert to MetaData<int> instead of MetaData<string>?
    Well, turns out we do know at an earlier conversion that always happens: converting our metadata to a string that will be put into the textbox. I cache the 'realtype' at that moment. (I'm not happy with that solution, if you know how to get rid of the obvious codesmell there, leave a comment!).

    The ConvertTo method is easy enough to not have to describe here, but in the ConvertFrom, we do have to jump through some hoops. I've opted to create a metadata<T> with reflection, using the correct type for T. Then, convert the passed in string to the correct type.

    This works brilliantly and it allows you to bind like this:

    <TextBox Text="{Binding Path=Name}" />

    (When it is time to navigate through a property, you will have to go through InnerValue again though, like {Binding Path=Car.InnerValue.Color} .)

    Microsoft's latest approach: IDataErrorInfo

    The WPF team has invented dependency properties as another way to do something similar (for different reasons though). You obviously do not want to use dependency properties in your domain model.

    The recently introduced IDataErrorInfo has the following definition:

            #region IDataErrorInfo Members

            public string Error
            {
                get { throw new NotImplementedException(); }
            }

            public string this[string columnName]
            {
                get { throw new NotImplementedException(); }
            }

            #endregion

    I hate that.

    Especially the name of the argument 'columnName'. Drives me mad. My business object is a person or a car, not a databasetable. F*ck off.

    Besides, what if you want to do something useful with an index on your object? Madness, I tell you!

    Conclusion

    It's annoying that you have to go to the innervalue property to get to the real value you are interested in. Implicit operators make this a lot more transparent but possibly confusing. Besides, there is a tiny performance loss here.

    However, you can do great stuff with such a setup. Let the metadataobjects implement INotifyPropertyChanged as well and use them in pipelines (more on this later), query validation rules from it without having to think about getting to the object that holds the property, and more.

    What do you think?

    Tuesday, 12 February 2008 20:08:58 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
     Saturday, 09 February 2008

    Dax Pandhi, of Reuxables is offering a lite version of their commercial theme: paper. You only get the compiled dll, but still, it's a bargain ;-)

    I have not used any commercial themes yet, and as I am not working for a client at this point, I probably won't at this moment ;-) I also do not know yet whether I like the theme. I am going to use it and just see!

    Are there other commercial theme packs around? I would like a pack that makes my applications look like this application ;-)

    Saturday, 09 February 2008 21:05:07 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

    If you are working with clients that do not see the use of automated testing (be it in unit tests of code blocks, or specific UI testing), you are in for a hard time. Maybe you should walk away, but let's face it: you will probably give in and try to do your best.
    I have even had heated discussions with developers that do not see the use of it, certainly when there are monkey-testers to do it.

    Testing the userinterface is incredibly hard to do. When you're testers are brave, they might use a testtool (robot) that will simulate clicks and read out information. However, these scripts have to be updated when the software changes and that is costly.

    WPF has great support for UI Automation, which allows other programs to interact with your application's UI from the outside. It does this by naming the elements of your UI and offers 'strategies' to interact with them (Press this button).
    It's not an easy framework, but workable.

    Project White seems to be an abstract layer on top of the UI Automation stack, released to the public domain by ThoughtWorks today. It's aimed at simplifying your scripts and presenting a uniform API for both Winform and WPF technologies.

    I'm looking forward to discovering it's api. This looks nice:

     

    Application application = Application.Launch("foo.exe");
       Window window = application.GetWindow("bar", InitializeOption.NoCache);
    Button button = window.Get<Button>("save");
    button.Click();

    Do you use UI automation to test your application?

    Saturday, 09 February 2008 20:54:33 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Monday, 04 February 2008

    I'm a strange man: I seem to be equally interested in EntityFramework and in WPF. They are such different beasts, and still I take great pleasure in using them both! That's possibly because I view them as enablers of the kind of projects I like to do. Weird.

    Anywho, it's been a long time since I blogged about WPF. And even longer since I blogged about unittesting WPF. The simple trick in this post is probably widely used already in the community: I haven't paid any attention ;-)

    In this post, I explained how to setup a tracelistener to listen for binding errors. In the months that followed, this proved to be less than convenient! In WPF views, even when everything is setup great, there might be binding errors that you wish to accept. For instance: a view binds to an instance of type Foo, and is later subsituted by an instance of type Bar. Bar has the same properties as Foo, except 1. The binding engine just clears the bound label, and you are fine with it (yes, sure.. it smells a bit, but you get the example).
    Using the tracelistener, you have less control over what the process.

    It is much better to have total control over the binding objects in a view. With some exceedingly simple methods, you can get to them to query their status:

    First, let's start with an enumeration over all the visuals in your view:

    public
    IEnumerable<Visual> EnumVisual(Visual visual)
    {
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
     {
       Visual childVisual = (Visual) VisualTreeHelper.GetChild(visual, i);
       yield return childVisual;
     }
    }

    Then, we use some cleverness by dr. WPF that enumerates all the bindings found on a visual:

    private IEnumerable<BindingExpression> EnumerateBindings(DependencyObject target)
    {
       if(target is ContentControl && ((ContentControl)target).Content is DependencyObject)
       {
          EnumerateBindings( (DependencyObject) ((ContentControl)target).Content);
       }

    LocalValueEnumerator lve = target.GetLocalValueEnumerator();

    while (lve.MoveNext())
       {
          LocalValueEntry entry = lve.Current;

          if (BindingOperations.IsDataBound(target, entry.Property))
          {
             Binding binding = (entry.Value as BindingExpression).ParentBinding;

             yield return entry.Value as BindingExpression;
          }
       }
    }

    It uses the GetLocalValueEnumerator, which is a largely unknown method that gets all the properties on a dependencyobject.
    I first check to see if the target is a content control, if it is, I go for its content as well.

    Now, let's see all the bindings:

    private IEnumerable<BindingExpression> GetFlattenedBindings(Visual root)
    {
       foreach (Visual child in EnumVisual(root))
       {
          foreach (BindingExpression childBinding in GetFlattenedBindings(child))
          {
             yield return childBinding;
          }

          foreach (BindingExpression binding in EnumerateBindings(child))
          {
             yield return binding;
          }
       }
    }

    Use it in your unittest to get all the bindings that are available in the visualtree. Test specific bindings or just fail if one breaks.

    foreach(BindingExpression b in GetFlattenedBindings(this))
    {
       Debug.WriteLine(b.ParentBinding.Path + "=" + b.Status + " on item:" + b.DataItem.ToString() );
    }

    Ofcourse, it's cool to change the helper methods to extension methods.

    Beware that I have not really tested the code. Copy pasting it, I see a few errors, but you get the drift.

     

    Monday, 04 February 2008 23:31:58 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
     Tuesday, 29 January 2008

    In my previous project, we used the Composite Application Block with WPF to decouple our application. Lately I have been thinking alot about this, and found some good material on the subject that I wanted to share. But first, let me give a high-level overview of my previous approach. If you are in need to first learn about MVP, check out this dnrTV video where Jean Paul Boodhoo talks about Model View Presenter.

    First off, keep in mind that CAB was not written for WPF and has to be hacked to actually be usable.
    Secondly, Acropolis is dead and is being turned into guidance material in the future (think end of 2008!).

    Cab exposes workitems, controllers and views. We approached the workitem as a simple configurator, which meant it just grabbed the view it wanted and showed it. That was all the responsibility a workitem got, even in wizard style screens.
    The controller was our main class, implementing all the screen logic. It was responsible for retrieving and saving data through services and did not communicate directly with the view. The only communication was through the model, that we dubbed as state.
    The view was bound to this state class, which could indeed be seen as a viewmodel-model (see Dan Creviers posts on this subject here). We kept the view as dumb as possible and only let it decide on view specific things, never implementing logic. This means, that the controller could decide when a particular state was prudent (for instance, 'this item is on sale'), but the view gets to decide how to present that item to the world ('wow, I'm going to turn the background to yellow').
    The codebehind of the view was only a translation layer between the WPF specific calls (events defined in Xaml) and calls to the controller.

    This worked great for us, although in hindsight, we did find that the whole solution was a bit over-the-top. We stuck with it though, and I think it worked out well enough. I feel we could have done without the workitems (in our approach atleast).

    Since I'm on sabbatical now, I've been reflecting somewhat more on this issue and found a series of incredible posts by Jeremy Miller on how to build your own CAB. Basically, he points out that it's not that hard to implement MVP in your application by building the pieces you need yourself. The upside would be that CAB is a big monster (I completely agree here),not worthy to be used in your kick-ass application (my own interpretation ;-) ) and building the components you need yourself would buy you a much more lightweight system custom fitted to your problem domain.

    While reading all of his posts, I kept feeling that most of what is needed for building a more loosely coupled system is already provided by WPF. The resources system is a possible way to inject dependencies and retrieve them. The routed events and usage of commands is also great. Then just now I've found a post which proves that I am right (and the rest of the world is wrong ;-) ) written by Josh Smith himself, a notable wpf blogger. He shows how he actually uses the resources system to inject classes and even mocks.

    My main interest at this moment is to decide how to build big systems with big teams and offer tangible guidance on that subject. One of the most important aspects of that is to Keep It Simple, Stupid! I saw that my team was strugling a bit with bending their minds around the whole MVC concept. This might be attributed to lacking explanations by myself, but at the very least, it was also caused by the feeling it brought-in more complexity then it took away. Certainly the less experienced of the team did not feel the de-coupling was worth it. That is why Jeremy's stand on this felt so 'right' for me. I do think that a simpler solution then CAB would be great.

    However, Joshes solution does feel a bit contrived to me. A view would indeed be able to find it's presenter(s), but how does the presenter find it's services? Will they also be defined within the resources? Could be. I find some piece of inversion of control is a more straight forward way to configure your components than 'misusing' the resources functionality. Because that's basically what is being done here.
    Keep in mind though, that it is mighty handy to be able to use the injected components within the userinterface without having to do weird things. Say you have an 'edit' button and a controller that was created to manage these things. Your view will want to bind the 'enabled' property to that controller. If it was injected somehow behind the scenes, you will have to find a way to bring it into scope for the button.
    We solved this, but it's not pretty!

    Another solution being worked on is a WPF specific MVC platform by Rob Eisenberg: Caliburn. His solution does tackle one important issue I have with current systems, which is the communication between the view and the controller. He introduces 'ActionMessages' which can be used in xaml like so:

    1.       <Button Content="="    
    2.               Margin="3">    
    3.          <Engine:Views.AddMessageSource>    
    4.             <Engine:ActionMessage Trigger="Click"    
    5.                                   Action="Divide"    
    6.                                   Return="{Binding ElementName=result, Path=Text}">    
    7.                <Engine:Parameter Value="{Binding ElementName=leftSide, Path=Text}" />    
    8.                <Engine:Parameter Value="{Binding ElementName=rightSide, Path=Text}" />    
    9.             </Engine:ActionMessage>    
    10.          </Engine:Views.AddMessageSource>    
    11.       </Button> 

    When the button is clicked, the method 'Divide' will be called on your controller, with two parameters. It's return value will be bound to the result textbox.

    Talk about a great idea!! He has used this framework for great succes and I can see why. Incredibly powerful.

    However, it does bring in yet another mechanism unfamiliar to your teammembers. Probably worth it though, I'm looking forward to delving into the project and using it myself.
    I don't like the introduction of yet another class of things that can go wrong at runtime though: the Action method (here: Divide) should exist on your presenter. If it's not, I'm sure you will only get an error at runtime. As if the binding syntax wasn't enough ;-)

    All in all, it seems there is lots of movement in the Microsoft community. People have been thinking about how to build userinterfaces for a long time, and I'm happy to see that this is also the case in the .Net world and very happy to see movement in the WPF camp on this front.

    More on this soon!

    Tuesday, 29 January 2008 00:19:38 (Romance Standard Time, UTC+01:00)  #    Comments [15]  |  Trackback
     Tuesday, 11 September 2007

    Some might remember that I was amongst the first to b*tch about not having a datepicker for wpf. Kevin Moore did his trick, and published a datepicker a long time ago. I'm very happy to see that a rich community is building around wpf. That has led to these two datepickers:

    • Farsi Library FX by Hadi Eskandari (here)
    • The datepicker from wpf contrib by Marlon (here)

    Have fun with these!!

    Tuesday, 11 September 2007 14:45:50 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Tuesday, 04 September 2007

    Monday morning, our application went live!! Hooray!!

    All seems to be going well, although one user had problems when starting the application:

    System.Windows.Markup.XamlParseException: Cannot convert string '0,0' in attribute 'StartPoint' to object of type 'System.Windows.Point'. Premature string termination encountered. Error at object 'LinearGradientBrush_1' in markup file 'PresentationUI;V3.0.0.0;31bf3856ad364e35;component/installationprogress.xaml'. ---> System.InvalidOperationException: Premature string termination encountered.

    The problem occured even before our application had downloaded. Notice the component/installationprogress.xaml: That's not ours, but belongs to the framework.

    I have seen these problems from time to time. We tried to fix it by re-installing the framework. (Sometimes, people have 6.715 instead of 6.920). That didn't work.

    In the end, we simply had to discard the users profile. I made a copy of the profile, so maybe I'll find the time to look into the issue in-depth, but I wanted to blog about it, because someone might be running into the same issue.

    Tuesday, 04 September 2007 11:18:24 (Romance Standard Time, UTC+01:00)  #    Comments [3]  |  Trackback
     Friday, 31 August 2007

    As we are scrambling to get our application ready for it's end-users, we are starting to notice some troublesome behavior by PresentationHost.exe: it tends to go up to 99% CPU-utilization and refuses to go down again.
    Obviously we have noticed PresentationHost going up very fast during our debugging sessions, but what goes up, always does go down again. However, now I'm receiving lots of reports from our end-users that claim the 'application is very slow'. This turns out to be that rogue process, which refuses to go down!!

    When we were able to attach windbg to it, we did not find a clear cause. It wasn't executing any of our code, to be sure. But it's definitely busy (no, there aren't any running animations!).

    We've also seen multiple instances of the process, where we'd only expect one.

    This is turning into a real headache. When we figure it out, I'll be sure to post!

    Friday, 31 August 2007 20:24:14 (Romance Standard Time, UTC+01:00)  #    Comments [3]  |  Trackback
     Thursday, 02 August 2007

    Just ran across a comment from Daniel Puzey here, with the following excellent advise:

    Often, by default, you'll get an error reported at Line 1 of the xaml, which is an obvious lie. You can catch the original exception, though:

    - Open the "Exceptions" window (Debug/Exceptions) in Visual Studio.
    - Click "add"
    - Add "System.Windows.Markup.XamlParseException"
    - Check the box to break on throw for this exception.
    - Hit F5!

    You'll find that the XamlParseException you catch is much more descriptive, and will give the correct position in the xaml file.

    Thursday, 02 August 2007 18:44:01 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Thursday, 26 July 2007

    When we just started utilizing WPF we didn't like the way converters had to be created for every little thing you wanted. We looked into using jscript for this after a forum post by Jonathan. At that point, we decided against it. However, he went ahead and created a fantastic package which hasn't had enough exposure imho. So take a look here.

    Basically, it will let you create inline code for simple converters. I wish I could use that now!

    Thursday, 26 July 2007 21:38:02 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Wednesday, 25 July 2007

    My team is scrambling to get a stable version of our application to our final test team! It's a very exciting time and things are going relatively easy. This is the time that small 'easy' things seem to work against you, as did a simple registry write:
    Our application is a corporate intranet distributed xbap, which gets full trust by means of a certificate. It's users are all local-administrators (say whaaattt??). I needed to write a key to a registry and this worked fine in visual studio debug mode. However, once hosted, the application crashed, due to insufficient access to the registry. I checked the permissions on the key, and it had full control for administrators.

    Giving the user group full control on the key did the trick. But why? I would have thought I had broken free of the sandbox by means of the certificate.

    Chango V. from the WPF team explains:'PresentationHost.exe runs with a restricted process token. In particular, it gives up the SIDs for the Administrators and Power Users groups.'
    That certainly explains it. Quite unexpected though. I probably haven't looked hard enough, but I couldn't find that in the SDK.

    Also, he mentioned: 'Yes, this is a design flaw in our hosting process. You get "full trust" from CLR point of view, but not in terms of NT security. We'll try to address this issue in a future release.'

    So there you have it. Keep that in mind when you develop full trust xbaps!

    Wednesday, 25 July 2007 20:06:27 (Romance Standard Time, UTC+01:00)  #    Comments [8]  |  Trackback
     Wednesday, 11 April 2007

    My project is migrating a big (very big) winform application to a WPF (using Xbap) application. At this point, only the front-end is touched. The team will eventually evolve into migrating the data-driven procedural backend to a process-centered, domain-driven, WF (Workflow foundation) managed solution.

    For this, we are looking for a few experienced C# developers. Obviously, WPF knowledge is a big plus. The project will last for quite a few months. When you walk away, you will have a deep understanding of WPF, CAB and WF.

    If this sounds like your cup of tea, please leave a comment or mail me directly. The project is based in The Hague.

    Wednesday, 11 April 2007 20:17:14 (Romance Standard Time, UTC+01:00)  #    Comments [8]  |  Trackback
     Sunday, 18 March 2007

    First off, I've returned from a great 7 weeks holiday in New Zealand. I will not bore you with 1500 pictures, although I am perfectly capable of doing just that. On top of that, 3 hours of film was shot. Yikes. It was just that incredible!

    For picking up the blogging slack, i'll share with you guys a mechanism for extending objects with attached properties. Although the technique is well documented, I didn't find any resources online with an example of a checked listbox. I did find a post by Josh Smith about it, but he created the checked listbox using the Checked and Unchecked events, which I don't feel is very 'WPF' like.. Not when you are using WPF! So, let's first look at the problem at hand, and then get on to the solution, which is so simple, it feels like an anti-climax.

    We have an ObservableCollection<T> with domainobjects, or in our case simple Strings. We wish to show these in a listbox, and give the user the abiliby to select multiple items using checkboxes. We also provide a button, which will just select all of them. Obviously, we want to be able to get to the checked items.
    In the past, I would probably have used checked and unchecked events to keep track of the checked items, or I would have extended my domainobject with a 'IsSelected' property and bind to it. The latter would have made me extremely unhappy, because it would mean my userinterface was invading my domainobject.

    An attached property, basically, is a property that belongs to another object, but can be set on any dependency object you choose. So, I will introduce a boolean attached property (for instance: IsGeselecteerd, dutch for IsSelected). Then I create the datatemplate for my objects, with a checkbox in it, and a binding to the attachedproperty:

     

    <Window.Resources> <DataTemplate x:Key="lbitems"> <StackPanel Orientation="Horizontal"> <CheckBox Name="checkbox" l:Window1.Geselecteerd="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}, Mode=TwoWay }" /> <Label Content="{Binding}" /> </StackPanel> </DataTemplate> </Window.Resources> <StackPanel> <ListBox Name="lv" ItemsSource="{Binding Path=Lijst}" ItemTemplate="{StaticResource lbitems}"> </ListBox> <Button Click="SelectAll">Select all</Button> <Button Click="LeesUit">show selected items in debug.output</Button> </StackPanel> </Window>

     

    The binding of interest is: l:Window1.Geselecteerd="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}, Mode=TwoWay }", on the checkbox.
    It means that the IsChecked property of itself (the checkbox) is bound to the property Geselecteerd, which lives on the Window1 class.

    That's basically all there is to it. Setting the checkboxes from procedural code is somewhat harder then I would like it to be, but only because I couldn't find an easy way to get to the checkbox from code:

     

    foreach(object dataitem in lv.Items) { // get the visual container, belonging to the dataitem ListBoxItem lbitem = (ListBoxItem)lv.ItemContainerGenerator.ContainerFromItem(dataitem); // get to the checkbox CheckBox c = (CheckBox) GeefChildHelper(lbitem, "checkbox"); // set the attached property SetGeselecteerd(c, true); }

    Point of interest is the setting of the attached property, which will tell the binding of the checkbox to do the appropriate thing and the Helper method, to get to the checkbox:

     

    private object GeefChildHelper(ListBoxItem lbitem, string naam) { Border border = VisualTreeHelper.GetChild(lbitem, 0) as Border; ContentPresenter contentPresenter = VisualTreeHelper.GetChild(border, 0) as ContentPresenter; return lv.ItemTemplate.FindName(naam, contentPresenter); }

    Here you see the need to first find a contentpresenter, before the FindName method will work..... That's because apparently that's the thing the template is bound to.

    Reading the values is just as easy:

     

    foreach(string dataitem in Lijst) { ListBoxItem lbitem = (ListBoxItem)lv.ItemContainerGenerator.ContainerFromItem(dataitem); CheckBox c = (CheckBox)GeefChildHelper(lbitem, "checkbox"); Debug.WriteLine(String.Format("item: {0} is {1}", dataitem, GetGeselecteerd(c).ToString())); }

    I hope this sample helps someone!

    AttachedList.zip (11.99 KB)
    Sunday, 18 March 2007 15:50:37 (Romance Standard Time, UTC+01:00)  #    Comments [7]  |  Trackback
     Sunday, 26 November 2006

    I encountered a rather annoying reflection exception that caused WPF dead in it's tracks during binding which I thought might be nice to share here.

    The problem arises when you bind against a property and WPF (or rather: reflection) can not determine which property you actually mean. This situation can occur when you have a property on a base class and you redefine (using the 'new' keyword) that property on a class that inherits from the base class. Here is some pseudo-code:

     

    public class mySpecialisation<T> : myBase { public new T myProperty { get { return (T)base.something; } } } public class myBase { public object myProperty { get { return something;} } }

    As you can see, the above situation might be a convenient way to construct your classes. However, it will throw an ugly exception.
    The obvious way to work-around this problem, is to make the property on the baseclass private or protected. However, in my case, I needed to get the the property through the baseclass as well. So I renamed the property in the inheritor and got rid of the exception. Kind of disappointing though!

    Sunday, 26 November 2006 22:50:50 (Romance Standard Time, UTC+01:00)  #    Comments [12]  |  Trackback
     Tuesday, 21 November 2006

    Although I love Xaml and the declarative person it makes me want to be, I feel even more strongly about fearless refactoring. If I fear renaming properties or moving types around, I do not refactor. And if I do not refactor regularly, my code begins to smell bad, which is a sure way to get my project featured the one place I do not want it ;-)

    So, I want to refactor, but Xaml makes me reluctant to do so. We do not set bindings in code behind, but we declare them (which I think is 'good') in Xaml. Visual Studio doesn't search Xaml files for binding-paths. And so I'm left in the dark about what impact my refactoring will have. Furthermore, binding-errors do not throw exceptions, but fail gracefully, leaving a naive unittest none the wiser.

    I've tried to catch the RoutedEvent 'Binding.Error' on a higher level, but it doesn't propagate.
    Nor does the LoadedEvent of controls, if the control does not explicitly call some Loaded eventhandler. In this approach I thought I would be able to catch the loaded event of the control while they are being put on the screen and register their binding to be checked later. If all your controls in question do declare a Loaded handler, then you could use something like this:

    EventManager.RegisterClassHandler(typeof(Control), Control.LoadedEvent,
    (RoutedEventHandler)delegate(object sender, RoutedEventArgs e)
    {

       // do your thing, throw an exception to let the unit test fail perhaps!
    }, true );

    But, like I said, this class handler will only fire if the control is already going to another Loaded event prior to this. Bummer.

    Another approach would be to write a visual tree walker and question all the bindings in the screen about their status (a property of BindingExpression). This could be some trouble, but should be very do-able.

    I've opted for yet another approach. I was using trusty Reflector to see how bindings work and discovered that binding errors are always shown in the output window. After some searching, it seems that even if you do not have any trace sources declared in your app.config, the visual studio debugger always switches the System.Windows.Data trace to the 'Warning'-level. And the warning level will trace a databinding error of code 35 if a binding is in error!

    Well, quite an obvious solution then is to create your own trace-listener class and registering it in the app.config. To get it to work, your unit test will have to do a refresh of the Tracesources to get the traces to work: PresentationTraceSources.Refresh();

    The Tracelistener:

    public class UnitTestTracer : TraceListener
    {
    public override void Write(string message)
    {
      // throw your exception to make trace fail!
    }

    public override void WriteLine(string message)
    {
      // throw your exception to make trace fail!

    }
    }

    And the app.config:

     

    <system.diagnostics>
    <sources>
      <source name="System.Windows.Data" switchValue="Warning" >
    <listeners>
      <add name="unitTestListener" type="UnittestTestWPF.UnitTestTracer, UnittestTestWPF" />
    </listeners>
    </source>
    </sources>
    </system.diagnostics>

     Simple, yet effective. The more I think about it, the more I like the approach!

    Tuesday, 21 November 2006 22:02:36 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
     Saturday, 11 November 2006

    The reason I haven't been blogging much lately is because I'm now heading up a team of developers that are porting a big Winform application to WPF. It's been a blast until now, but I've been too busy to blog. We're using CAB as a means to decouple logic from presentation (MVC-pattern) and one of my developers has been blogging quite heavily about it here.

    Let me go into some more detail on the whole WPF experience. As I said, we are porting the client-side of a big application (about 250 screens). We're doing it as an XBAP (Xaml browser application) to enable us to easily distribute it in our intranet. Although this does force us to install a certificate (to gain full-trust), we're not seeing major drawbacks to this approach.
    WPF already decouples presentation from code a great deal more then winforms do, but combining it with MVC does give it a whole new dimension. Setting up a simple screen does mean creating a few more classes then we're used to, so we're looking into using the Guidance Automation Tools (GAT) to speed-up development time.

    In my honest opinion, WPF is a truly great technology. It does what it promises, but there are a few drawbacks. First of all, I do feel it's kind of slow. Resizing a screen with a lot going on, definitely feels 'heavy'. So that's a bummer (stay away from drop-shadows, they will kill your performance). Furthermore, we are starting to see some places where XAML is not cutting it. For instance, triggers lack power on the equation and multi-bindings are always &&-nd together. Also, some 'bugs', like always clearing validation-errors after a binding update-to-target.
    These are all minor things and we can work-around them. It does mean a very steep learning curve for my new developers.

    It was a great feeling, when I saw my designteam checking-in controlstyles and my developers not being hindered at all by their work. All the pieces fell into place and that was quite unlike my previous experiences with winforms.

    Saturday, 11 November 2006 23:10:31 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
     Tuesday, 08 August 2006

    An article has just been published on code project by Josh Smith that should not escape your attention: Piping value converters in WPF.

    Basically, he has written a simple class that will allow you to define a group of converters and use it during databinding like so:
        <local:ValueConverterGroup x:Key="statusForegroundGroup">
          <local:IntegerStringToProcessingStateConverter  />
          <local:ProcessingStateToColorConverter />
          <local:ColorToSolidColorBrushConverter />
        </local:
    ValueConverterGroup>

    and then use it like so:

            <TextBlock
              Text="{Binding XPath=@Status,
                     Converter={StaticResource statusDisplayNameGroup}}"

              Foreground="{Binding XPath=@Status,
                           Converter={StaticResource statusForegroundGroup}}"
    />

    This should prove very valuable indeed!

    Tuesday, 08 August 2006 08:46:39 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Monday, 31 July 2006

    A small tip today on how to access elements that are embedded within a control template. In my case for an itemscontrol class.
    Consider the following Xaml:

    <ItemsControl

        x:Class="Client.Framework.TijdslijnVisualizer.TijdslijnVisualisatie"

        xmlns:cf="clr-namespace:Client.Framework.TijdslijnVisualizer"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        >

      <ItemsControl.Style>

        <Style TargetType="{x:Type ItemsControl}">

          <Setter Property="Template">

            <Setter.Value>

              <ControlTemplate TargetType="{x:Type ItemsControl}">

                <DockPanel LastChildFill="True">

                  <Slider Name="slider" DockPanel.Dock="Right" Minimum="1" Maximum="10" Value="1" Orientation="Vertical" />

                  <ScrollViewer Name="scroller" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="False">

                    <cf:TijdslijnPanel Name="tijdslijnpanel"  IsItemsHost="True" zoomFactor="{Binding ElementName=slider, Path=Value }" />

                  </ScrollViewer>

                </DockPanel>

              </ControlTemplate>

            </Setter.Value>

          </Setter>

        </Style>

      </ItemsControl.Style>

    </ItemsControl>

     

    In the code behind for this class you will not be able to simply get the to these elements with ease. Or at least, not until I realized that these elements were not set yet until the template was actually applied. If you try to find them after that, you will find them through the VisualTreeHelper.GetChild or a simple .FindName:

     

            public override void OnApplyTemplate()

            {

                base.OnApplyTemplate();

     

                this.slider = (Slider) this.Template.FindName("slider", this);

                this.scroller = (ScrollViewer) this.Template.FindName("scroller", this);

     

                // other stuff

            }

     

    I hope this helps somebody out there!

     

    Monday, 31 July 2006 14:46:33 (Romance Standard Time, UTC+01:00)  #    Comments [5]  |  Trackback
     Friday, 28 July 2006

    Just a little tip, showcasing the power of Xaml and the efficiency of good code/design separation.

    When you are fetching data from a server, you could (and actually should) use the DataModel-View-ViewModel pattern, as described by Dan Crevier from the Microsoft Max team. It uses a viewmodel-class to bind your Xaml against. Dan then implements a 'state' property to indicate whether the model is finished fetching and is in a 'bindable' state.

    If you are short on time, or have other reasons not to implement such a strategy, you are probably binding straight to objects that are still Null during the fetch-action.
    In either case, it would be nice to let the user know that data is being fetched.

    In my case, I had a lot of <TabItem>'s that are being filled with data, one-by-one, by setting the datacontext directly. While designing the user interface, I do not want to have to think about the possibility of binding against an invalid object (it being null). So I created a style, that I put in the application resources. The style replaces my content-template with a temporary template, whilst in invalid state. I was extremely satisfied with the solution, because it was so dead-easy, and it works like a charm.

    Here is the code (don't mock my visually stunning border please ;-) ):

        <Style BasedOn="{StaticResource {x:Type TabItem}}" TargetType="{x:Type TabItem}">

          <Style.Triggers>

            <Trigger Property="DataContext" Value="{x:Null}">

              <Setter Property="ContentTemplate">

                <Setter.Value>

                  <DataTemplate>

                    <Border CornerRadius="5" BorderThickness="2" BorderBrush="Black" Background="Yellow" Height="60" Width="280"

                            HorizontalAlignment="Center" VerticalAlignment="Center">

                      <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Data is being fetched</TextBlock>

                    </Border>

                  </DataTemplate>

                </Setter.Value>

              </Setter>

            </Trigger>

          </Style.Triggers>

        </Style>

    I was pleasantly surprised by the simplicity of the code. The DataContext is used in a trigger to set the content-template.

    Friday, 28 July 2006 14:48:29 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Wednesday, 26 July 2006

    Microsoft apparently had reasons not shipping WPF with a datepicker control. In my opinion such a control is of great importance when you are building applications. How can I sell a platform to a client when I have to explain that they won't be able to visually enter a date? (Or have to hire me to build such a control for them ;-) )
    Some time ago I started a forum thread about this issue and the ATC Avalon responded by taking up the challenge and started working on a control. Why that team was dismissed is beyond me, but Kevin Moore finished where they left off. He has posted an update to his bag-of-tricks for the July CTP (they also work on the June CTP), and has included the datepicker sample!

    I've quickly checked it out and it's looking great! I wish I could use empty dates though, but that should be easy to hack in.
    Thanks Kevin!

    Wednesday, 26 July 2006 09:42:24 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
     Wednesday, 12 July 2006

    I love Dependency Properties. Especially attached properties. There is just something extremely cool about being able to think up some property and then setting that in a datatemplate. For instance, creating a custom panel with your own attached properties, and reading these properties during the measure and arrange bits of the layout.
    But when you do a get on the property, you will find your left with an unset value!

    The backing mechanism for such properties use the object you set them on as a key. When you only have a UIElement, you can not read the value using the UIElement, because you never bound the property to a UIElement, but to your own visual in the datatemplate.
    So always remember to use the original object when you are getting your value.

    In the case of the UIElement in an itemscontrol, you will find that it is actually a wrapper around your original visual. Get to it by using the infamous visual tree helper:

    DependencyObject o = VisualTreeHelper.GetChild(uie, 0);

    Then use 'o' in your getvalue!

    Wednesday, 12 July 2006 09:39:06 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Tuesday, 20 June 2006

    The sdk team has published all the WPF beta 2 samples as a zip. They are right here, http://www.wcsdkteam.members.winisp.net/wpfsamples.zip. Leave comments about problematic downloads at the sdk blog.

    Tuesday, 20 June 2006 13:35:01 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
     Monday, 12 June 2006

    When you are creating a layout in Xaml, you should be careful to take into account the width you have left. Yes, WPF will try to be smart and scale your controls, but what if the content of your control does not want to be scaled?

    Paste this into Xaml-Pad and resize your Window:

    <Grid Width="Auto" Height="40" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
                xmlns:d='clr-namespace:System.Windows.Data;assembly=PresentationFramework' >
    <Button HorizontalAlignment="Left">A lengthy button</Button>
    <TextBlock HorizontalAlignment="Center">An longer TextBlock</TextBlock>
    </Grid>

    Nick Thuesen has a solution for this. He has created 3 rangeConverters that allow you to plug in a width and set a range where you would like your control to be visible. That is cool, I like it, I will use it.
    In my specific case though, I wanted to collapse the content of a control based on the width of it's container. Basically, the container is a border, and it's content is a stack panel with some text boxes. The container is sized by an algorithm, so the container is more important then the content. The panel that does this scaling is surrounded by a slider, which zooms the controls accordingly. When enough space is available, the content should become visible.
    Since I do not know the range in which the content should be shown, I can't use his controls.

    It was dead simple to create my own though. Instead of using a single binding converter, I've used the MultiValueConverter to be able to bind to multiple properties.

    public class ClippingToVisibilityHiddenConverter : IMultiValueConverter
    {
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
    Debug.Assert(values.Length == 2);

    double availableWidth = Double.PositiveInfinity;
    Double.TryParse(values[0].ToString(), out availableWidth);

    double desiredWidth = 0d;
    Double.TryParse(values[1].ToString(), out desiredWidth); // possibly unset

    double margin = 0d;
    if (parameter != null)
    Double.TryParse(parameter.ToString(), out margin);

    Console.WriteLine("Desired: {0}, avail: {1}", values[1].ToString(), availableWidth.ToString());
    return desiredWidth > (availableWidth-margin) ? Visibility.Collapsed : Visibility.Visible;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
    throw new Exception("not implemented");
    }
    }

    Usage is equally simple:

    <StackPanel.Visibility>
    <
    MultiBinding Converter="{StaticResource ClippingConverter}" ConverterParameter="15" >
    <
    Binding Path="ActualWidth" RelativeSource="{RelativeSource AncestorType={x:Type ContentPresenter}, AncestorLevel=1}" />
    <
    Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
    </
    MultiBinding>
    </
    StackPanel.Visibility>

    There you go, I hope you're happy with it! Confusion though about the ActualWidth property of elements....

    My custom panel that does the layout, determines the desired size of the elements by doing a measurement of the element. Then at the arrange-pass, it calls an arrange on the element with a size possibly smaller then it desires. Somehow, when you read back the ActualWidth, DesiredSize, RenderSize or what else you can think of, you will never find that passed-in size.

    Well, call me st00pid, but I would have expected the RenderSize to let me get to the .... rendered size..  ;-)
    It does not.

    Since I so desperately do want to find that 'clipped' size, I set the render size myself, after the arrange:

    Size s = new Size(days * pixelsPerDay, uie.DesiredSize.Height);
    uie.Arrange(new Rect(new Point(tsLinks.Days * pixelsPerDay, 0), s));
    uie.RenderSize = s; // oh dear

    It's definition in the SDK: Gets (or sets, but see Remarks) the final render size of this element.
    So, the remarks then: Do not attempt to set this property, either in XAML or in code, if using the Windows Presentation Foundation (formerly code-named "Avalon") framework-implemented layout manager (nearly all common application scenarios will be using this framework layout manager). The layout manager will not respect sizes set via this property directly...

    Yikes.

    I like feeling naughty, but feeling this naughty can't be good.
    I'll keep it in though, until I find a way to bind to the actual ActualWidth.

    Monday, 12 June 2006 14:38:30 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
     Thursday, 08 June 2006

    I always use Expression Interactive Designer when I want to see the full default style of a control, but here I have found a equally easy way: just dump it into XML.

    Style style = FindResources(typeof(Button)) as Style; //Get button's default Style
    if (style != null)
    {
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.IndentChars = new string(' ', 4);
    StringBuilder strbuild = new StringBuilder();
    XmlWriter xmlwrite = XmlWriter.Create(strbuild, settings);
    XamlWriter.Save(style, xmlwrite);//Use XamlWriter to dump the style
    return strbuild.ToString();
    }

    It uses the findresources method to find a style and then just writes it out. Might come in handy!

    Thursday, 08 June 2006 19:43:13 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
     Wednesday, 07 June 2006

    My previous post was about not being able to bind to a named element outside of your scope. With the help of some great people, we figured out a workaround: you can bind to an ancestor. So, this does work:

    <StackPanel DataContext="{Binding ElementName=lb, Path=SelectedItem}">
    <
    ListBox Name="lb" ItemsSource="{Binding Source={StaticResource InventoryData}, XPath='Book'}" IsSynchronizedWithCurrentItem="True" />
    <
    local:CustomItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Path=DataContext}" />
    </StackPanel>

    This has a listbox that binds to a datasource (xml this time) and a stackpanel above it binds it's datacontext to the selecteditem of the listbox.
    Obviously this has all kinds of nasty smells surrounding it.... Next please!

    We might not be able to bind to a named element outside of scope, but if we can bind to an ancestor, chances are good that we can bind to a staticResource as well. So let's introduce a CollectionView around our XML datasource. In the Window.Resources:
    <CollectionViewSource x:Key="InventoryView" Source="{Binding Source={StaticResource InventoryData}, XPath='Book'}" />

    And then we can bind to the currentitem of this view, instead of the ugly datacontext of the parent stackpanel:

    <StackPanel >
    <
    ListBox Name="lb" ItemsSource="{Binding Source={StaticResource InventoryView}}" IsSynchronizedWithCurrentItem="True" />
    <
    local:CustomItemsControl ItemsSource="{Binding Source={StaticResource InventoryView}, Path=CurrentItem}" />
    </
    StackPanel>

    This is a good enough workaround for now. ;-)

    Wednesday, 07 June 2006 19:40:44 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

    I've been working hard on seemingly simple functionality. I have a usercontrol (derived from ItemsControl) which has a panel (the itemshost) and a few other things like so:

    <ItemsControl x:Class="VisualizerUsercontrol.myVisualizer"
                  x:Name="parentControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <ItemsControl.Style>
        <Style TargetType="{x:Type ItemsControl}">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ItemsControl}">
                <StackPanel Orientation="Horizontal">
                  <Button>press me</Button>
                  <ScrollViewer VerticalScrollBarVisibility="Auto">
                    <StackPanel Orientation="Horizontal"
                                IsItemsHost="True" />
                  </ScrollViewer>
                </StackPanel>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </ItemsControl.Style>
    </ItemsControl>

    When instantiating the control on a window, I bind it's ItemsSource to some other control, like a listbox's selectedItem. This of course, for a master-detail view. The bug is that this ItemsControl is unable to resolve it's ItemsSource, because the Element for which it is looking, is in another scope.

    That actually is kind of unpleasant, and I hope to find a workaround for it. I appear not to be alone in this finding, and the consequences of it really limit the use of a usercontrol severely.

    Wednesday, 07 June 2006 15:29:55 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback