Archive for the ‘Samples’ Category

MVVM – The no code behind challenge

Glenn Block has an excellent post titled “The spirit of MYYM, it’s not a code counting exercise”. The post can be found at CodeBetter.

I thoroughly enjoyed the post and greatly appreciate practical discussions on WPF/SL application patterns. I am a bit of a WPF nut having lived and breathed xaml for over 2 years. I’ve been a part of 2 successful WPF projects (both in production). In both scenarios I acted as the defacto WPF guru.

This last project was a typical line of business application and we used the ViewModel pattern with Prism. I bring all this up to share my background with WPF and ViewModels.

Concerning the content of the post, I agree with Glenn on the majority of the content. The Commands and Parameters especially rings true. I found that whenever I went with option A [using element binding to a command parameter] I ended up refactoring it to option B [binding the ‘selected’ item to a property on the ViewModel]. Although a neat use of xaml, in practice the binding to the property just allowed more flexibility that indubitable becomes necessary with future changes and demands (not to mention testing opportunities).

With both projects we didn’t have the luxury of a full time designer. In both scenarios I argued there was plenty of work for a designer, but alas the resources just weren’t there. We were able to use a designer for a decent chunk of hours, but more could have been done. The applications were definitely better off for having every hour we could get from any designer resource. I believe the last project persuaded many that indeed there was enough work for a full time designer, so maybe I can hope for a designer with a future application.

I say this because I can not speak towards what its like having a designer in Blend all the time working on Views. When we used a designer resource, they would work in Blend and then a go-between developer / designer would take the xaml and integrate it with our ResourceDictionaries.

What I would like to address is the ‘no code behind’ philosophy compared to the code behind practicality.

Two years ago when I was floundering for WPF information and blogs, I ran across a blog post (I want to say it was Josh Smith) where the writer stated something like : “if something is easier to do in the code behind then its okay to do it in the code behind.”

He was arguing that a crap load of xaml vs a couple lines of code behind isn’t an argument at all. The code behind is the best choice. Naturally clearer intentions and code maintainability takes precedence over having a dogmatic “everything in xaml” approach.

With this last LoB Prism application, we had some choices to make when we were deciding on how the client should be made up.

Do we use UserControls as Views or (as Ryan Riley brought up) do we use Data Templates as views. I felt at the time the team wasn’t ready for that leap to Data Templates as views. I considered the code behind of a User Control as a placebo safety net for a team struggling with the WPF learning curve. What I did do was firmly encouraged a no code behind policy. A “no code behind” challenge if you will.

If I were to go back to the beginning and make that View decision again, I would go with the Data Templates as views. The team did very well without using the code behind. A Data Template view would have brought more benefits than the cost of having no code behind. Often we found ourselves thinking.. if this view was a data template and not a user control, then we could more easier do X.

I have championed the “no code behind” stance internal to Catapult and to other developers. Yes you can legitimately use the code behind to accomplish certain tasks. More often than not though (in my experience), the use of the code behind has more to do with the prejudices carried over from WinForms development. Having a strict no code behind stance forces developers to learn and change the way they think about coding functionality into the UI.

Glenn came up with a scenario (albiet a overly simplified one) of where he felt a code behind had some value. The scenario described is:

‘”The user clicks a Save button on the Edit Order screen which requires some UI cue to the user such as an hourglass while the order is saving, and another cue once the Order has saved.”

He argues that the code in the xaml is less testable. He even suggests the solution I made. He also recognizes others my disagree. Count me in the disagreement camp.

I created a simple project that uses Attached Dependency properties to accomplish this simple scenario. This isn’t a “throw down the gauntlet” sort of thing and I didn’t really write it for Glenn. A coworker emailed Glenn’s blog and I responded in an email describing my solution. He then asked to see it in action. So I coded it up.

He also asked me to post a comment on Glenn’s post, but I don’t really see the point especially since I agree with the information Glenn is sharing and his opinions are built on experience & expertise. I really had no disagreement and the solution Glenn already knows of. /shrug

Anyway.. you can find the solution here : http://github.com/RookieOne/AttachedAnimation/tree/master

Toggling Read Only with WPF

Ayende tweeted a brief code snippet of some WPF he threw together (well I assume he threw it together).

You can see the code snippet here : http://pastie.org/568259

He asked : Someone PLEASE tell me there is a better way than this (WPF)

I tweeted a brief snippet response to improve that tiny bit. The snippet can be found here : http://codesnippets.joyent.com/posts/show/2221

But I couldn’t just leave it at that. I wanted to show a different approach to solving the same problem.

How can we make a control ‘read only’ through binding?

The solution can be found here on my Git Hub Repository : http://github.com/RookieOne/WpfTogglingReadOnly/tree/master

Ignoring all the other machinations, the money xaml is in the TextBoxStyle found in the Styles\TextBoxStyles.xaml resource dictionary.

<Style x:Key="TextBoxStyle" TargetType="TextBox">        
    
    <Style.Triggers>
        
        <DataTrigger Binding="{Binding IsReadOnly}" Value="True">
 
            <!-- Readonly Template -->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <TextBlock Text="{TemplateBinding Text}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            
        </DataTrigger>
        
    </Style.Triggers>
    
</Style>

As you can see I use the IsReadOnly property on the base view model as a data trigger and then completely swap out the control template for the text box. This allows for complete customization of the read only look. It also pushes this functionality out into a style to be reused through the entire application.

Other things to note with the project (for those unfamiliar with the following practices):

1. Data Templates as Views
<DataTemplate DataType="{x:Type PersonView:PersonViewModel}">

So whenever WPF tries to resolve the PersonViewModel in a container, it will use this DataTemplate since I did not provide a key but only a DataType.

So in Window1 I can do…

<ContentControl>
    <PersonView:PersonViewModel />
</ContentControl>

 
Again this is a very simple scenario so I am ignoring any presentation patterns on how the ViewModel is placed or ‘shown’. Also ignoring how dependencies can be resolved, etc.
 
And even though this is a content control, this works for items controls as well. So consider a stack of ‘views’. You could be accomplish this simply by placing a collection of ViewModels in an ItemsControl.
 
But really… that’s for another post.
 
2. Expression for INotifyPropertyChanged

I am also using a LambdaExpression to implement INotifyPropertyChanged. Essentially achieving safe notification and eliminating those nasty magic strings.

public string FirstName
{
    get { return _firstName; }
    set
    {
        _firstName = value;
        OnPropertyChanged(this, m => m.FirstName);
    }
}

Anyway.. that was a quick project I threw together. I hope it was helpful.

Acase().for(patternType.FluentInterfaces).create()

When I was first exposed to the idea of fluent interfaces my response was… big flipping deal.

It wasn’t until I actively started using fluent interfaces in my code did I begin to see their power and elegance.

What is a fluent interface? Here is the obligatory link to wikipedia ;)

In simple terms, its returning a type instead of void in order to achieve method chaining.

The end goal of the method chaining is to provide a more readable interface and code.

First, does it break the Law of Demeter?

Law of Demeter doesn’t equal the number of periods. I am of the opinion fluent interfaces do not violate the Law of Demeter.

What is LoD? Another link to wiki and here is a link to a stack overflow on this very subject! :)

To me, Law of Demeter is about restricting communication between objects.

A common violation of LoD (imho) is the exposure of a list property on an object. I believe this serves as a good example of LoD as well as being an example on how to make a fluent interface. :)

A Person object has a name and a list of friends.

   1:      public class Person
   2:      {
   3:          public string Name { get; set; }
   4:          public List<Person> Friends { get; set; }
   5:   
   6:          public Person()
   7:          {
   8:              Friends = new List<Person>();
   9:          }
  10:      }

I could then add friends by…

 
   1:  var roger = new Person{ Name="Roger" };
   2:  roger.Friends.Add(new Person { Name = "Eddie" });
   3:  roger.Friends.Add(new Person { Name = "Freddie" });
   4:  roger.Friends.Add(new Person { Name = "Gordie" });

Now this is pretty typical, so what’s the problem?

Well my code knows WAY too much about Person. I know it has a list of friends and if they change that list to say a dictionary, I am hosed.

Not only that, but poor Person class… people can add friends to his collection without him every knowing. What if some additional logic needs to be done when adding a friend?

What if the person wants to record the birth date of every friend so they can send out birthday cards? Person is SOL.

As for Law of Demeter, my code is using the Person object to communicate through to the List<Person>. I am exposing my code to changes in Person.

Let’s change Person to eliminate this problem.

   1:      public class Person2
   2:      {
   3:          public string Name { get; set; }
   4:          private readonly List<Person2> _friends;
   5:   
   6:          public Person2()
   7:          {
   8:              _friends = new List<Person2>();
   9:          }
  10:   
  11:          public void AddFriend(Person2 friend)
  12:          {
  13:              _friends.Add(friend);
  14:          }
  15:      }

Now the only way to add a friend is through Person. Yippie!

 

   1:  var roger2 = new Person2 {Name = "Roger"};
   2:  roger2.AddFriend(new Person2 { Name = "Eddie" });
   3:  roger2.AddFriend(new Person2 { Name = "Freddie" });
   4:  roger2.AddFriend(new Person2 { Name = "Gordie" });

 

If I wanted to make this a fluent interface all I would need to do is instead of returning void, return the Person class.

   1:      public class Person3
   2:      {
   3:          public string Name { get; set; }
   4:          private readonly List<Person3> _friends;
   5:   
   6:          public Person3()
   7:          {
   8:              _friends = new List<Person3>();
   9:          }
  10:   
  11:          public Person3 AddFriend(Person3 friend)
  12:          {
  13:              _friends.Add(friend);
  14:              return this;
  15:          }
  16:      }

Now I can do the same logic like…

   1:  var roger3 = new Person3 { Name = "Roger" }
   2:                              .AddFriend(new Person3 { Name = "Eddie" })
   3:                              .AddFriend(new Person3 { Name = "Freddie" })
   4:                              .AddFriend(new Person3 { Name = "Gordie" });

That is pretty cool, but fluent interfaces really shine with the builder pattern.

This time around I want to force construction of a person through a builder and have the builder use a fluent interface. Notice my Person’s constructor and fields are private. I embed the builder class within the Person class so the builder has access to the constructor and fields. In this manner only my builder class has access to constructing a person. My builder can now act as an anti-corruption layer for Person.

   1:      public class Person4
   2:      {
   3:          private string _name;
   4:          private List<Person4> _friends;
   5:   
   6:          private Person4()
   7:          {
   8:              _friends = new List<Person4>();
   9:          }
  10:   
  11:          public Person4 AddFriend(Person4 friend)
  12:          {
  13:              _friends.Add(friend);
  14:              return this;
  15:          }
  16:   
  17:          public static PersonBuilder createAPerson()
  18:          {
  19:              return new PersonBuilder();
  20:          }
  21:   
  22:          public class PersonBuilder
  23:          {
  24:              private Person4 _person;
  25:              public PersonBuilder()
  26:              {
  27:                  _person = new Person4();
  28:              }
  29:   
  30:              public PersonBuilder named(string name)
  31:              {
  32:                  _person._name = name;
  33:                  return this;
  34:              }
  35:   
  36:              public PersonBuilder withFriend(Person4 friend)
  37:              {
  38:                  _person.AddFriend(friend);
  39:                  return this;
  40:              }
  41:   
  42:              public PersonBuilder withaFriendNamed(string name)
  43:              {
  44:                  var friend = createAPerson().named(name).finish();
  45:                  _person.AddFriend(friend);
  46:                  return this;
  47:              }
  48:   
  49:              public Person4 finish()
  50:              {
  51:                  return _person;
  52:              }
  53:          }
  54:      }

Now to create Roger and his friends I do..

 
   1:  var roger4 = Person4.createAPerson()
   2:                      .named("Roger")
   3:                      .withaFriendNamed("Eddie")
   4:                      .withaFriendNamed("Freddie")
   5:                      .withaFriendNamed("Gordie")
   6:                      .finish();       

It’s a simple example but maybe it sparked some ideas on how to use fluent interfaces to chain methods and make your code more approachable to people without Computer Science degrees. :D

JB

Future-proofing Office 2003 Custom Menu Development

More and more companies are slowly rolling out Windows Vista as they bring on new machines. However, if you’ve tried upgrading an Office 2003 document that uses custom menus, you will have noticed that those custom menus don’t appear in Office 2007’s new Ribbon. Well, that’s not entirely true; they do appear in the Add-Ins tab. However, leaving users to figure that out for themselves is not a little unkind.

You might think your only option is to create two files–one for Office 2003 and previous and another for Office 2007. You would be wrong. Instead, you can use an Excel 2007 Add-In to extend the ribbon when the file is opened in Office 2007 and open the file as normal in Office 2003. Ron de Bruin explains how to do this in his post “Dealing with Ribbons and Menus – Avoiding Two Versions.”

To make this work, you’ll need the CustomUIEditor from OpenXMLDeveloper.org. Also, I’ve always been a big fan of class modules, so I have attempted to roll all this up into one class module, following Ron’s second example.

Here’s the code for the CustomMenu.cls class:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "CustomMenu"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'******************************************
' Class:        CustomMenu
'
' Created by:   Ryan Riley (Catapult Systems)
' Created on:   5/22/2008
'
' Description:  This class allows menus and menu items to be added
'               to assist the user with additional reporting options.
'
' Dependencies: None
'******************************************

Option Explicit

'******************************************
' Private Members
'******************************************
Private mstrName As String            ' Use an '&amp;' to assign a shortcut key.
Private mstrRibbonxPath As String     ' Store the Excel 2007 Add-in path.
Private mstrRibbonxName As String     ' Store the Excel 2007 Add-in filename.
Private mcolMenuItems As Collection
Private mcbc As CommandBarControl

'******************************************
' Class C'tors and D'tors
'******************************************
Private Sub Class_Initialize()
    ' Initialize the Name property.
    mstrName = "My Menu"
    mstrRibbonxPath = ThisWorkbook.Path
    mstrRibbonxName = "RibbonxAddin.xlam"
    Set mcolMenuItems = New Collection
End Sub

Private Sub Class_Terminate()
    ' Destroy the menu item collection object.
    Set mcolMenuItems = Nothing

    ' Destroy the CommandBarControl object.
    Set mcbc = Nothing
End Sub

'******************************************
' Public Properties
'******************************************
Public Property Get Name() As String
    Name = mstrName
End Property

Public Property Let Name(ByVal value As String)
    mstrName = value
End Property

Public Property Get RibbonxPath() As String
    RibbonxPath = mstrRibbonxPath
End Property

Public Property Let RibbonxPath(ByVal value As String)
    mstrRibbonxPath = value
End Property

Public Property Get RibbonxName() As String
    RibbonxName = mstrRibbonxName
End Property

Public Property Let RibbonxName(ByVal value As String)
    mstrRibbonxName = value
End Property

'******************************************
' Public Methods
'******************************************
' Add a menu to the document.
Public Function Attach( _
  Optional Before As Integer = 0) As Boolean
    ' Initialize the function return value.
    Attach = False
   
    If Val(Application.Version) &gt; 11 Then
        If (Dir(mstrRibbonxPath &amp; "\" &amp; mstrRibbonxName) &lt;&gt; "") Then
            Workbooks.Open mstrRibbonxPath &amp; "\" &amp; mstrRibbonxName
        Else
            MsgBox "The RibbonX add-in (" &amp; mstrRibbonxName &amp; ") could not be found."
        End If
    Else
        AddMenu Before
    End If

    ' If all has gone well, return true.
    Attach = True
End Function

Public Function Detach()
    Detach = False

    If Val(Application.Version) &gt; 11 Then
        On Error Resume Next
        Workbooks(mstrRibbonxName).Close False
    Else
        DeleteMenu
    End If

    Detach = True
End Function

' Add menu items to the menu. Call this for each menu
' item you wish to add to the menu.
Public Function AddItem( _
  ByVal Name As String, _
  ByVal Macro As String) As Boolean
    AddItem = False
   
    If (Val(Application.Version) &gt; 11) Then
        ' Add the menu item to the private collection.
        mcolMenuItems.Add Macro, Name
    Else
        ' Add a menu item to our new menu, give it a caption,
        ' and tell it which macro to run (OnAction).
        With mcbc.Controls.Add(Type:=msoControlButton)
            .Caption = Name
            .OnAction = Macro
        End With
    End If

    AddItem = True
End Function

' Define the function for all Ribbon controls to call when executed.
' This method execute the button that matches the format:
' "buttonName" where Name is the Menu Item name.
Public Function OnActionCall(MenuItem As Variant) As Boolean
    Dim RibbonItem As IRibbonControl

    ' Initialize the return value.
    OnActionCall = False

    ' Set the MenuItem to the RibbonItem as an implementation
    ' of the IRibbonControl.
    Set RibbonItem = MenuItem

    ' Run the macro that matches that stored in the collection.
    Application.Run mcolMenuItems(Mid(RibbonItem.ID, 7))

    ' If all goes well, return true.
    OnActionCall = True
End Function

'******************************************
' Private Methods
'******************************************
Private Function AddMenu( _
  Optional Before As Integer = 0) As Boolean
    Dim cbMainMenu As CommandBar
    Dim intBeforeIndex As Integer

    ' Initialize the function return value.
    AddMenu = False

    ' Delete any existing menus with the same name.
    ' We must use On Error Resume next in case it does not exist.
    On Error Resume Next
    Application.CommandBars("Worksheet Menu Bar").Controls(mstrName).Delete
    On Error GoTo 0
   
    ' Set a CommandBar variable to use for the Worksheet menu bar
    Set cbMainMenu = Application.CommandBars("Worksheet Menu Bar")
   
    ' If the Before Index is &gt; 0, set the Before Index to the passed
    ' in index; otherwise set it to the index for the last menu.
    If (Before &gt; 0 And Before &lt;= cbMainMenu.Controls.Count) Then
        intBeforeIndex = Before
    Else
        intBeforeIndex = cbMainMenu.Controls.Count
    End If

    ' Add "My Menu" to the Main Menu CommandBar, just before the last menu.
    ' Set a CommandBarControl variable to it
    Set mcbc = cbMainMenu.Controls.Add( _
        Type:=msoControlPopup, Before:=intBeforeIndex)
                     
    ' Set the menu control's caption to the provided name.
    mcbc.Caption = mstrName

    ' If all has gone well, return True
    AddMenu = True
End Function

Private Function DeleteMenu() As Boolean
    On Error Resume Next
   
    ' Initialize the function return value.
    DeleteMenu = False
   
    ' Remove the menu added earlier.
    Application.CommandBars("Worksheet Menu Bar").Controls(mstrName).Delete

    DeleteMenu = True
End Function

As for the implementation, you could do something like this to get the same affect as Ron’s Example 2 (above):

Option Explicit

Const RibbonxAddin As String = "HasRibbonX.xlam"
Private menu As CustomMenu

Private Sub Workbook_Open()

    Set menu = New CustomMenu

    menu.Name = "Test Tab"
    menu.RibbonxPath = ThisWorkbook.Path    ' Default
    menu.RibbonxName = RibbonxAddin
    menu.Attach
    menu.AddItem "A", "BtnA"
    menu.AddItem "B", "BtnB"
    menu.AddItem "C", "BtnC"
End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    menu.Detach
   
    Set menu = Nothing
End Sub

Sub OnActionCall(MenuItem As Variant)
    menu.OnActionCall MenuItem
End Sub

Using this approach, you’ll be able to add in your custom menu/ribbon for all users of your custom Office development.