Export (0) Print
Expand All
This topic has not yet been rated - Rate this topic

New in This Release

This minor update of the Composite Application Guidance for WPF and Silverlight allows you to use the Composite Application Library with Silverlight 3. The following changes were implemented in this release:

  • All Visual Studio projects (Composite Application Library, reference implementation, and Quickstarts) were migrated to use Silverlight 3. If you do not want to upgrade to Silverlight 3, see Opening Projects with Silverlight 2.
  • TabRegionControlAdapter was modified to support binding in the TabItem's control header in Silverlight 3. This feature was present for Silverlight 2 but stopped working in Silverlight 3 due to a breaking change. It now supports both versions of Silverlight.
  • Implemented the WeakEvent Pattern for the DelegateCommand's and CompositeComand's CanExecuteChanged event to fix a possible memory leak in the applications using the Composite Application Library commands. For more information, see Composite Application Library Command Memory Issues and Solution.
  • CreateXap.bat file was modified to search for Silverlight 3 assemblies if the Silverlight 2 reference assemblies cannot be found. This is to support the infrastructure required to run the Composite Application Library unit tests. Applications already using the library will not be affected.

Opening Projects with Silverlight 2

If you have the Silverlight 2 tools installed, you will receive the following error when you open projects built using Silverlight 3 in Visual Studio:

Unable to read the project file: The imported project "C:\Program Files\MSBuild\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

In order to get the additional benefits of this new release, such as fixes to commands, but still use Silverlight 2, you should modify the <Import> path in the project files (files ending with *.csproj, typically Composite.Silverlight.csproj, Composite.Presentation.Silverlight.csproj, and Composite.UnityExtensions.Silverlight.csproj) to point to the Silverlight 2 installation path instead. For example, if you have the following Import element:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v3.0\Microsoft.Silverlight.CSharp.targets" />

Update the version so that it refers to the Silverlight 2 tools path as shown below:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />

Composite Application Library Command Memory Issues and Solution

Cause of Issue

In situations where the lifetime of a view and the lifetime of an ICommand bound to that view differ, it is possible to introduce memory leaks with typical .NET Framework events. To overcome this, commands should implement the Weak Event Pattern to ensure that the view weakly subscribes to the CanExecuteChanged events for the DelegateCommand and CompositeCommand implementations of ICommand. This scenario is common in applications that use the Composite Application Library because DelegateCommands are instantiated and referenced by view presenters or ViewModels, and controls in the views bind to them. This issue also affects global commands.

Solution

Implemented the WeakEvent Pattern for the CanExecuteChanged event of the DelegateCommand and CompositeCommand classes.

Breaking Change

Consumers of CompositeCommand and DelegateCommand classes that subscribe to the CanExecuteChanged event using code (not when binding using XAML) will need to keep a hard reference to the event handler. This is to prevent garbage collection of the event handler as the command no longer has a hard reference to this handler. An example implementation can be seen in the CompositeCommand and CommandBehaviorBase classes. In most scenarios, there is no reason to sign up to the CanExecuteChanged event directly, but if you do, you are responsible for maintaining the reference.

How to Avoid Garbage Collection of Events Subscribed Using Code

To avoid the garbage collection of the event handler when subscribing to other commands' CanExecuteChanged events, CompositeCommand instances must keep a reference to its own handler. To achieve this, the CompositeCommand class was modified in this version, and can serve as an example if you are subscribing to a command's event using code.

  1. Added an EventHandler private property and initialized it in the constructor:
    private readonly EventHandler registeredCommand_CanExecuteChangedHandler;
        
          public CompositeCommand()
    {
            registeredCommand_CanExecuteChangedHandler = new EventHandler(this.RegisteredCommand_CanExecuteChanged);
    }
    

  2. When subscribing or unsubscribing to the CanExecuteChanged event of the registered commands, used the handler shown in the following code, instead of using the method name for the handler:
    public virtual void RegisterCommand(ICommand command)
    {
    ...
    
        command.CanExecuteChanged += this.registeredCommand_CanExecuteChangedHandler;
        this.OnCanExecuteChanged();
    
    ...
    }
    
    public virtual void UnregisterCommand (ICommand command)
    {
    ...
    
        command.CanExecuteChanged -= this.registeredCommand_CanExecuteChangedHandler;
        this.OnCanExecuteChanged();
    
    ...
    }
    

This same approach was also implemented for the CommandBehaviorBase because it is also subscribing to the CanExecuteChanged event of the commands using code.


Home page on MSDN | Community site

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.