Category Archives: Software Design Patterns

Unit Testing an MVVM RelayCommand

The RelayCommand is an excellent way to communicate between a view and View Model in MVVM without creating a link to a specific instance of either. However; one problem that I recently encountered when using these was: how are they unit tested.

Take the following piece of code (taken from https://tfsutilities.codeplex.com/):


    public class MainViewModel : ViewModelBase
    {          
        public RelayCommand FindOrphanedWorkspaceCommand { get ; private set ; }

This is instantiated here:

         public MainViewModel( IDataService dataService)
        {
            ...

            FindOrphanedWorkspaceCommand = new RelayCommand(FindOrphanedWorkspaces);

And, finally, the method itself:

         /// <summary>
        /// Call method to retrieve all workspaces that currently have no pending changes
        /// </summary>
        private void FindOrphanedWorkspaces()
        {
            // Doesn't really matter what this actually does

So; can we just write a test; what about this:

    [TestClass]
    public class MainViewModelTest
    {
        [ TestMethod]
        public void FindOrphanedWorkspaces()
        {
            IDataService ds = new Mock.MockDataService ();
            MockMainViewModel mvm = new MockMainViewModel (ds);

            mvm.FindOrphanedWorkspaceCommand();

        }

The answer, of course, is no (otherwise this wouldn’t be a particularly useful blog post).

The Workaround

There is a workaround (which is pretty much by fallback workaround these days when I find something can’t be unit tested for reasons of protection):

Simply change the private method to protected and subclass the viewmodel:

    class MockMainViewModel : MainViewModel
    {
        public MockMainViewModel( IDataService dataService) : base (dataService) { }

         public void FindOrphanedWorkspaces()
        {
            base.FindOrphanedWorkspaces();

This certainly works and, in its defence, it tests as completely as calling the RelayCommand (I don’t believe testing the MVVM architecture is within the remit of the test architecture of any dependent program).

However…

It feels like a lot of additional work (as it happens, it’s work you may have to do anyway for other things, but that’s beside the point). So, what’s the alternative?

RelayCommand implements ICommand, here’s the metadata:


namespace GalaSoft.MvvmLight.Command
{
    // Summary:
    //     A command whose sole purpose is to relay its functionality to other objects
    //     by invoking delegates. The default return value for the CanExecute method
    //     is 'true'. This class does not allow you to accept command parameters in
    //     the Execute and CanExecute callback methods.
    public class RelayCommand : ICommand
    {
        // Summary:
        //     Initializes a new instance of the RelayCommand class that can always execute.
        //
        // Parameters:
        //   execute:
        //     The execution logic.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     If the execute argument is null.
        public RelayCommand( Action execute);
        //
        // Summary:
        //     Initializes a new instance of the RelayCommand class.
        //
        // Parameters:
        //   execute:
        //     The execution logic.
        //
        //   canExecute:
        //     The execution status logic.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     If the execute argument is null.
        public RelayCommand( Action execute, Func< bool> canExecute);

        // Summary:
        //     Occurs when changes occur that affect whether the command should execute.
        public event EventHandler CanExecuteChanged;

        // Summary:
        //     Defines the method that determines whether the command can execute in its
        //     current state.
        //
        // Parameters:
        //   parameter:
        //     This parameter will always be ignored.
        //
        // Returns:
        //     true if this command can be executed; otherwise, false.
        public bool CanExecute( object parameter);
        //
        // Summary:
        //     Defines the method to be called when the command is invoked.
        //
        // Parameters:
        //   parameter:
        //     This parameter will always be ignored.
        public virtual void Execute( object parameter);
        //
        // Summary:
        //     Raises the GalaSoft.MvvmLight.Command.RelayCommand.CanExecuteChanged event.
        public void RaiseCanExecuteChanged();
    }
}

Consequently, you can simply do this:


        [ TestMethod]
        public void FindOrphanedWorkspaces()
        {
            IDataService ds = new Mock.MockDataService ();
            MockMainViewModel mvm = new MockMainViewModel (ds);

            mvm.FindOrphanedWorkspaceCommand.Execute( null);

        }

And, there’s more. If you’ve implemented the CanExecute, you can test if that works; for example:

Assert.IsTrue(mvm.FindOrphanedWorkspaceCommand.CanExecute(null));

Or

Assert.IsFalse(mvm.FindOrphanedWorkspaceCommand.CanExecute(null));

In my case, as it stands, the former.

Conclusion

So, we can check whether the command can execute, and whether it does execute. Admittedly this isn’t ground-breaking research, but it took me longer that it should have to figure it out, and next time, I’ll have a blog post to refer to.

Implementing single cell copy and full row Item Selection in WPF DataGrid

Recently, I came across a strange problem with a DataGrid while using the MVVM-Light pattern. The problem was that I needed to implement two, seemingly similar pieces of functionality:

1. To copy any given cell in the data grid
2. To search the database, based on a specific piece of data in the selected row of the datagrid (regardless of which cell was selected).

To implement the Copy feature was unbelievably easy – you don’t even need a custom command; just add the following setting to the DataGrid:

SelectionUnit ="CellOrRowHeader"

And the following context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
       <MenuItem Command="Copy"/>                    
    </ContextMenu>
</DataGrid.ContextMenu>

And the copy is done!

So, next, I wanted to implement the custom search. I needed to identify the currently selected row in my ViewModel, so I added a new property:

        private MyDataClass _selectedItem;
        public MyDataClass SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                RaisePropertyChanged(() => SelectedItem);
            }
        }

I then bound this to the selected item of the datagrid, like this:

     < DataGrid ItemsSource ="{ Binding Path =MyDataCollection}"                   
                  SelectedItem="{ Binding Path =SelectedItem}"                   
                  SelectionUnit ="CellOrRowHeader"  
&#91;/sourcecode&#93;

And finally, created my command:

&#91;sourcecode language="csharp"&#93;
         public RelayCommand MyCommand { get ; private set ; }
&#91;/sourcecode&#93;

In the constructor, initialised it:

&#91;sourcecode language="csharp"&#93;
     this.MyCommand = new RelayCommand (() => this.MyCommandFunc());

Created the function:

         private void MyCommandFunc()
        {
            QueryDB(SelectedItem.ValueOne);
        }         

And, finally, setup the context menu:

<DataGrid.ContextMenu>
    <ContextMenu>                    
         <MenuItem Command ="Copy"/>                    
         <MenuItem Header ="My Funky Command" Command="{Binding MyCommand}"/>
    </ContextMenu>
</DataGrid.ContextMenu>

But this didn’t work! (Queue dramatic music).

The problem is down to this:

SelectionUnit ="CellOrRowHeader"

So, change it to:

SelectionUnit="FullRow" 

And it works again… but now copy doesn’t work, because it copies the FULL ROW!

So, the two features are incompatible?

I did find a workaround which doesn’t breach the separation of concerns. Please note that, although this does work, and does not breach separation of concerns, it may or may not be the best way of doing it. If you have, or know of, a better way the PLEASE leave a comment, or mail me and let me know.

The Workaround

Instead of binding the SelectedItem property, bind the Tag property of the grid:

< DataGrid ItemsSource ="{ Binding Path =MyDataCollection}" Tag="{ Binding Path =SelectedItem}" SelectionUnit ="CellOrRowHeader" [/sourcecode] Now, we need a little code-behind, which must remain agnostic to the ViewModel: [sourcecode language="csharp"] private void DataGrid_SelectedCellsChanged( object sender, SelectedCellsChangedEventArgs e) { (( DataGrid)sender).Tag = ((DataGrid)sender).SelectedCells.FirstOrDefault().Item; } [/sourcecode] Now, because the SelectedItem is bound in the view to the Tag, updating the Tag, updates the SelectedItem. This means that when you call your function (as described above): [sourcecode language="csharp"] private void MyCommandFunc() { QueryDB(SelectedItem.ValueOne); } [/sourcecode] SelectedItem is now set. Conclusion

Whilst I can see why this works the way it does, it doesn’t seem sensible that I need to jump through so many hoops to get this to work without breaking the separation of concern. It may just be a quirk with the DataGrid, but it feels like a hack – which I don’t like. Nevertheless, ATM it’s the only solution that I can come up with that doesn’t mean directly referencing the View from the ViewModel.

Implementing a call to search using MVVM Light

I recently started using the MVVM Light framework to create an app. One of the first things that I found tripped me up was trying to link the ViewModel functionality with the visual interface. After a little more searching than should be necessary I came across the concept of commands. Basically, thos allows you to bind the functionality of your view model to an action on the screen. In the example below it’s the action of clicking a button.

First, create a new relay command (this is in the namespace GalaSoft.MvvmLight.Command):

    public class MainViewModel : ViewModelBase
    {
        private readonly IDataService _dataService;

        /// <summary>
        /// The <see cref="WelcomeTitle" /> property's name.
        /// </summary>
        public const string WelcomeTitlePropertyName = "WelcomeTitle" ;

        private string _welcomeTitle = string.Empty;

               // New Command Variable
        public RelayCommand SearchCommand { get ; private set ; }
        ...

Next initialise the command in the constructor of the VM:

        public MainViewModel( IDataService dataService)
        {
            this.SearchCommand = new RelayCommand (this.GetDataCount);
            ...

Obviously, the execute function must exist. For example:

        private void GetData()
        {
                _dataservice.GetData((count, error) =>
                {
                    if (error != null)
                    {
                        // Report error here
                        return;
                    }

                    // Do something with data here
                });
        }

Finally, simply add a call from the XAML in MainWindow:

Parameters

You can also pass parameters, by simply providing the CommandParameter attribute and then using it. However, given that you’re already in the databound context (i.e. you’re function is in your ViewModel, which is bound to the DataContext) I didn’t find a need for this, as it’s possible to simply reference the property directly.

Conclusion

This ends up being quite a neat way to link the two. The screen is linked to the view model without having a chunk of code in the button click handler.