MVVM uses for ApplicationCommands.Close

ApplicationCommands.Close is an example of a RoutedCommand (it’s actually a descendant RoutedUICommand). RoutedCommands are a special case in WPF which when executed fire a RoutedEvent which can then be handled up the in the Visual Tree. It’s a special case becase it doesn’t follow the ICommand interface; for it to work it requires Execute and CanExecute to take an extra parameter: CommandTarget.

In order to get this extra parameter it must be bound to an ICommandSource, such as a button which knowns to pass in an IInputElement into Execute and CanExecute. This makes using it in MVVM a little difficult as we would need a View element in our ViewModels.

People often think about using ApplicationCommands.Close with MVVM and Dialogs. It would be nice to bind a CompositeCommand to a Save button for example; the first command saves the second command being the ApplicationCommands.Close would trigger the dialog to close. Unfortunately there is no CompositeCommand that supports RoutedCommands and I’m not sure the concept of RoutedCommands supports the Composite Pattern (there is a possiblility here to investigate).

There are still uses for ApplicationCommands.Close in MVVM however.
If like PopUpBehaviour, your dialogs use an ApplicationCommands.Close  CommandBinding to close the Window or PopUp, binding a Close Button to ApplicationCommands.Close is an easy way to close the dialog.

In Part 2 I’ll look at how to use ApplicationCommands.Close as the signal for closing Dialogs/Windows.

EventToCommand Action – MVVM Glue

One of my favourite additions to WPF is the Blend Interactivity library which allows you to decorate behaviour into controls in XAML. This really is the glue that allows you to work around MVVM problems in third-party libraries or the framework itself.

The following is an example of a Trigger and Action, to bind SelectedItems to a ViewModel as it changes. This work around is required as SelectedItems isn’t bindable.

<ListBox Name="ItemsToChoose">
  <i:Interaction.Triggers>
    <!-- Can't bind directly to Selected Items 😦 -->
    <i:EventTrigger EventName="SelectionChanged">
      <Command:ChangePropertyOnTarget
          Target="{Binding}" PropertyName="SelectedItems"
          Value="{Binding SelectedItems, ElementName=ItemsToChoose}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox

One of the most common scenarios for me is the need to execute a command when a control raises a particular event. For instance double-clicking an item in a ListView. The MVVM Light Toolkit has  a great TriggerAction called EventToCommand which has been a great help, allowing me to redirect an event and turn it into a command as such:

<ListBox Name="list">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDoubleClick">
      <Command:EventToCommand
           Command="{Binding Path=DataContext.DoSomethingCommand,ElementName=list}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox>

There are two small short-comings with the original. Firstly that it provides no access to the EventArgs. I have tweaked the original to add an EventArgs which you can use in your bindings of the command parameter. (Source Here)

This example shows the tweaked EventToCommand, passing in the DataContext of the clicked row.

<ListBox Name="list">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseDoubleClick">
      <Command:EventToCommand
           Command="{Binding Path=DataContext.DoSomethingCommand,ElementName=list}"
 CommandParameter="{Binding EventArgs.OriginalSource.DataContext, RelativeSource={RelativeSource Self}}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListBox>

I have also rectified the second issue; it doesn’t implement ICommandSource so it does not handle RoutedCommands.

Requery Not Suggested

During my first WPF project I noticed (like most people starting in WPF do) that DelegateCommand.CanExecute is called once and never refreshed. To force a refresh one must call RaiseCanExecuteChanged when the state of CanExecute has changed. That had a few smells about it and was cubersome, so when I stumbled across CommandManager.RequerySuggested I thought all my problems were solved.

From MSDN ”Occurs when the CommandManager detects conditions that might change the ability of a command to execute.”

All I did was create my own DelegateCommand and proxy the CanExecutedChanged event to the CommandManager.RequerySuggested event and every time WPF noticed something change it would force a refresh of my CanExecute methods. I even had the audacticity to call it BetterDelegateCommand!!

This didn’t cause too many problems on the project, as a general rule people know to keep the CanExecute logic quick and we had linear navigation in the application so there wouldn’t have been more than 10 commands bound at anyone point.

Things quickly change when you move to apps that have multiple windows/dialogs/plugins loaded and hundreds of commands can be bound. Spice that up with a developer adding CanExecute methods that do a little more than test the value of a variable and you get a significant slowdown which is very hard to debug.

Because there are times when using the RequerySuggested method is preferable Present.Commands provides the RequeryCommandDecorator and fluent method.

MyCommand = Command.Async(new SomeAction())
                   .ToCommand()
                   .SuggestRequery();

For everything else there is the CanExecuteChangedDecorator and fluent command. It allows you to specify an Observable which it subscribes to, when a notification comes through the CanExecuteChanged event is fired. Using an Observable adds a powerful filtering and joing tool to define when the command ‘s state has changed.

  MyCommand = Command.Async(new SomeAction())
                                .ToCommand()
                                .CanExecuteChangedWhen(this.WhenPropertyChanges(x => x.SomeProperty));

Everything needs a ViewModel – CollectionViewModel

CollectionViewModelThe title is a little misleading; but everyone loves generalisations and WPF. 😉
It may have been better named view-first decomposition or something similarly benign.

One of the big issues people face when implementing MVVM is collections (example, example), primarily how do I keep my model in sync. 

The reason; IMO, is that people tend to compose their ViewModels based on the models they are trying to display on-screen. Whilst this is not a bad idea (mainly because screens tend to be modelled on the models as well 🙂 ) solutions often come from a design-first approach whereby your ViewModels represent parts of the screen (not necessarily parts of the model or only a single model).

As an example take a Customer who has a collection of Addresses. When we create ViewModels based on the Model we tend to only see our objects i.e. Customer and Address. When we see a collection the first reaction is whack in a ObservableCollection.

 When creating the view that contains a collection it will often be displayed as some type of ItemsControl. The ItemsControl will often contain buttons for Adding, Deleting, Moving etc. When we look at it from the perspective of screen decomposition it becomes much clearer that there is some list component there which needs a ViewModel.

Once we come to this realisation the CollectionViewModel becomes self-evident. It’s responsibility is to maintain the underlying model; when a ViewModel is deleted from the collection it deletes the corresponding model from the underlying collection, same for add and move. I do this by listening to CollectionChanged event and providing the collection with mapping methods between ViewModel and Model.

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
           base.OnCollectionChanged(e);

  if (SyncIsDisabled)
                return;

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
  foreach (var item in e.NewItems)
  AddToModel((TViewModel)item);
                    break;

                case NotifyCollectionChangedAction.Remove:
  foreach (var item in e.OldItems)
  RemoveFromModel((TViewModel)item);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    underlyer.Clear();
                    break;

            }
        }

So when decomposing screens or models into ViewModels; or when you encounter an issue with a design, double-check everything is a ViewModel.

MVVM Animation of ListBox – Present.Commands

http://vimeo.com/17851405

Using the Present.Command decorator to change visual states after a command execution we can easily animate the addition and deletion of items in a WPF ListBox in an MVVM friendly way.
(The code is in svn for the async command samples)

Firstly, our ViewModel’s: we have an ItemViewModel representing an item in the ListBox; and an ItemCollectionViewModel representing our ListBox. Our ItemCollectionViewModel contains the two commands we are primarily focused on, Add and Delete.

AddCommand

  AddCommand = Command.Async
               (
  AsyncAction.FromDelegatesItemViewModel>()
                       .Do(x => new ItemViewModel("New Item "))
  .OnSuccess(Add)
  .ToAction()
  .SuccessVisualState(ItemVisualStates.Add)
  ).ToCommand();

Pretty self-explanatory, we create a new item, Add it to the collection and change the state of the new item viewmodel to “Add”

DeleteCommand

DeleteCommand = Command.Async
                (
                    AsyncAction.FromDelegates<ItemViewModel, ItemViewModel>()
                        .Do(e =>
                                {
                                    e.Parameter.IsDeleting = true;
                                    Thread.Sleep(2000);
                                    return e.Parameter;
                                })
  .ToAction()
  .SuccessVisualState(ItemVisualStates.Delete, item => Remove(item))
  ).ToCommand();

The delete command is a little more involved. We set the Parameter (the item to delete) to “deleting” and sleep to simulate server call. Once we have deleted it on the server we play the delete animation (by changing the visual state to delete) and then once everything is finished we remove the item from the collection.

ListBox Item DataTemplate

 <DataTemplate>
          <!--Register the View, so it is acessible from Services, bind the current visual state so the ViewModel can control it-->
          <UniformGrid Name="grid" Style="{StaticResource DemoGrid}"  VerticalAlignment="Center" Commands:PresentVisualStateManager.GoToState="{Binding State}"
                       Core:ViewRegistry.Register="true">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="ActionStates">
                <VisualState x:Name="Add"  Storyboard="{StaticResource AddAnimation}"/>
                <VisualState x:Name="Delete"  Storyboard="{StaticResource DeleteAnimation}"/>
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <Button Command="{Binding DataContext.DeleteCommand, ElementName=List}" CommandParameter="{Binding}" Height="20" Width="20">
              <Button.Style>
                <Style TargetType="Button" BasedOn="{StaticResource ImageButton}">
                  <Style.Triggers>
                    <DataTrigger Binding="{Binding IsDeleting}" Value="True">
                      <Setter Property="Content">
                        <Setter.Value>
                          <Viewbox Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Button.Height}">
                            <Progress:CircularProgressBar />
                          </Viewbox>
                        </Setter.Value>
                      </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding IsDeleting}" Value="False">
                      <Setter Property="Content">
                        <Setter.Value>
                          <Image Source="{StaticResource imgMediumCross}"
                                 Width="{TemplateBinding Button.Width}"
                                 Height="{TemplateBinding Button.Height}" />
                        </Setter.Value>
                      </Setter>
                    </DataTrigger>
                  </Style.Triggers>
                </Style>
              </Button.Style>
            </Button>

              <Label Content="{Binding Name}" />

          </UniformGrid>

        </DataTemplate>

Here we define the VisualStates Add and Delete and their corresponding animations (static resources)
We change the Button image to a circular progress bar whilst we are deleting.
We register the View with the ViewRegistry and bind to the delete command.
With a little more designer input we have a beautiful animating listbox 😉

Visual State Change In a Command

Using the Present VisualStateManager and the ViewRegistry we can now use a Present.Commands  decorator  to change the visual state of a ViewModel after succesful execution of the decorated command.

 The decorator has a number of overloads, the ViewModel to change state of can be passed in or returned by the do action; an action can be executed after the state transition as well.

  AddCommand = Command.Async
               (
                   AsyncAction.FromDelegates<object, ItemViewModel>()
                            .Do(x => new ItemViewModel("New Item "))
                            .OnSuccess(Add)
                   .ToAction()
                   .SuccessVisualState(ItemVisualStates.Add)
               ).ToCommand();

The view has to then register itself with the registry and define a VisualState using the constant passed into the fluent method.

Putting the View in ViewModel – A ViewRegistry

One of the great things that MVVM has achieved is removing the dependency on the View in the ViewModel (Presenter). Occasionally, however,  I run into situations where I really need to know what View the ViewModel is associated with.

I need to create a dialog; which window is the owner? Or which control is the owner for pop-ups?

I want to change the Visual State with a call-back ; Which control do I pass to the VisualStateManager?

Having rejoiced that I no longer have a dependency on the View from my ViewModel, how do I get a reference to a ViewModel’s View?

The best solution I have seen thus far is the concept of a ViewRegistry. The ViewRegistry is dictionary of Views keyed by the View’s ViewModel. A View that knows it uses Dialogs or the VisualStateManager, for instance, registers itself with the ViewRegistry via an attached property. The ViewRegistry adds the View using it’s DataContext (the ViewModel) as the key. The View Registry handles the removal of unloaded views to ensure memory leaks don’t occur.

<UserControl pc:ViewRegistry.Register="true" ... >

It’s also good to note that a “View” can also be any control inside an actual view, this can be useful with things like the PopUp Dialog where you want the dialog to control a portion of a view.

  <Grid pc:ViewRegistry.Register="true" ... >

I shy away from ever injecting the ViewRegistry into a ViewModel, as this starts to bring back the coupling MVVM fought so hard to remove. Rather being viewy the ViewRegistry is used in more viewy services like the Dialog Service or Visual State Manager Service.

A View can be retrieved like this:

UIElement view = viewRegistry.FindViewFor(viewModel);

The ViewRegistry class is from Present.Core and can be viewed here.

Accidental De-Virtualization

WPF’s UI Virtualization allows you to bind a large collection of data to a control without requiring the control to create a UI Element for each item in your collection. It does this by using Virtualizing Panels such as the VirtualizingStackPanel.

Recently I had a collection of 15,000 elements being bound to a ListView ( a different issue) and it was taking up seconds to do so!! After a frustrating performance search looking for rogue server calls on the UI Thread I opened up Snoop to discover 15,000 ListViewItems in my VirtualizingStackPanel; WTF?

There are a number of things that can disable the Virtualization of a control (this is not an exhaustive list of reasons why virtualization may not be working)

  • Not using DataBinding
  • VirtualisationMode, IsVirtualising, CanContentScroll properties set incorrectly
  • Grouping Enabled
  • Changing the ControlTemplate or ItemsPanel to a non-virtualizing panel
  • Not supported by the control

In my case, as verified by Snoop, my ListView was using a VirtualizingStackPanel. I had however overridden the wrong control template in order to get fixed headers and had rendered my virtualization moot. (By having my ItemsPresenter not being directly descendant of my ScrollViewer)

If your having trouble binding large sets of data, and you need to do it, ensure your using a Virtualizing Panel (and that there’s only a handful of items in it).