Search Wiki:
References:
Smart Client Contrib project has a WPF Cab Visualizer
CAB Visualizer download on CodePlex
CAB Visualizer disposes WorkItems
CAB Event Visualizer

IMPORTANT INFORMATION
Notice that my SCSFVisualizerBase (below) derives from WinFormsVisualizer versus CabVisualizer; I originally started with CabVisualizer and could not understand why the WinFormsVisualizer kept being instantiated and initialized; this was problematic because it's CreateVisualizationShell() method is sealed and I didn't want the default "VisualizerForm" - so I figured I'd simply use CabVisualizer and then override it's CreateVisualizationShell() since it was virtual; this was not going to happen....

Please reference this static structure diagram (it has the important details). I show the ShellApplication's inheritance down to CabApplication which performs it's Run() method. In this diagram you will find that the WinFormsVisualizer is tightly coupled as it is defined as the VisualizerType in the WindowsFormsApplication() constructor. As a result it won't matter what baseclass you specify for your visualizer - it will default to WinFormsVisualizer. There is a way to override this but to simplify usage of my sample I used the defaults.

Before I go into my theory as to why a loosely coupled framework tightly coupled this visualizer let me give an example of how you can override this default behavior:

In the ShellApplication.cs add the following VisualizerType declaration:
        protected ShellApplication()
        {
            VisualizerType = typeof(CabVisualizer);
        }
 

So why tightly coupled.... If you reference the above visio diagram our answer lies in the VisualizerType property comments - if VisualizerType is null then visualizations support is turned off, even if configured in App.Config. The reason this is the case is evident in the CreateVisualizer() method (also in the diagram). So a default of WinFormsVisualizer locking you into it's CreateVisualizationShell() method.

CodePlex SDMS app (Change Set: 15376) contains an activated demo screenshot follows:
CabVisualizer.gif

App.Config requirements follow:
  <configSections>
    <section name="CompositeUI" 
                 type="Microsoft.Practices.CompositeUI.Configuration.SettingsSection, Microsoft.Practices.CompositeUI"
                 allowExeDefinition="MachineToLocalUser" 
    />
  </configSections>
 
  <CompositeUI>
    <visualizer>
      <add type="SCSFLibrary.Visualizers.SCSFVisualizer, SCSFLibrary" />
    </visualizer>
  </CompositeUI>

Visualizer code follows:
namespace SCSFLibrary.Visualizers
{
    public class SCSFVisualizer : SCSFVisualizerBase
    {
        [InjectionConstructor]
        public SCSFVisualizer(WorkItem rootWorkItem, IVisualizer visualizer)
            : base(rootWorkItem, visualizer) { }
 
        public override void AddViews()
        {
            base.AddViews();
 
            // Brad Wilson
            // http://www.codeplex.com/smartclient/WorkItem/View.aspx?WorkItemId=7046
            ShowViewInWorkspace<WorkItemVisualization>("MainWorkspace", null);
            
            // David Platt
            // http://www.rollthunder.com/Newsletter/newslv8n3.htm
            AddTab<EventVisualizerControl>("MainWorkspace", "Events");
        }
    }
}

SCSFVisualizerBase.cs follows:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.CompositeUI.WinForms;
using Microsoft.Practices.ObjectBuilder;
using Microsoft.Practices.CompositeUI;
using TraceToolWrapper;
using Microsoft.Practices.CompositeUI.SmartParts;
 
namespace SCSFLibrary.Visualizers
{
    public class SCSFVisualizerBase : WinFormsVisualizer
    {
        WorkItem _visualizerWorkItem;   // you must add this line
        IVisualizer _visualizer;        // and this line
 
        public WorkItem VisualizerWorkItem
        {
            get { return _visualizerWorkItem; }
        }
        public WorkItem AppWorkItem
        {
            get { return _visualizer.CabRootWorkItem; }
        }
 
        public SCSFVisualizerBase() {}
 
        // Our hook into the visualizer 
        [InjectionConstructor]
        public SCSFVisualizerBase(WorkItem rootWorkItem, IVisualizer visualizer)
            : this()
        {
            _visualizerWorkItem = rootWorkItem;
            _visualizer = visualizer;
 
            AddViews();
        }
        public virtual void AddViews() { }
 
        protected void AddTab<TView>(string workspaceName, string tabTitle)
        {
            TView view = VisualizerWorkItem.Items.AddNew<TView>();
 
            ISmartPartInfo info = new TabSmartPartInfo();
            info.Title = tabTitle;
            VisualizerWorkItem.RegisterSmartPartInfo(view, info);
            IWorkspace ws = VisualizerWorkItem.Workspaces[workspaceName];
            VisualizerWorkItem.Workspaces[workspaceName].Show(view);
        }
 
        /// <summary>
        /// Creates and shows a smart part on the specified workspace.
        /// </summary>
        /// <typeparam name="TView">The type of the smart part to create and show.</typeparam>
        /// <param name="workspaceName">The name of the workspace in which to show the smart part.</param>
        /// <returns>The new smart part instance.</returns>
        protected TView ShowViewInWorkspace<TView>(string workspaceName, WindowSmartPartInfo windowInfo )
        {
            string title = "WorkItem";
            TView view = VisualizerWorkItem.SmartParts.AddNew<TView>();
            try
            {
                if (windowInfo != null)
                {
                    // By default WorkItem will be used - if windowInfo provided
                    // then override title with provided information
                    VisualizerWorkItem.RegisterSmartPartInfo(view, windowInfo);
                    title = windowInfo.Title;
                }
 
                if (workspaceName != null)
                    VisualizerWorkItem.Workspaces[workspaceName].Show(view, new SmartPartInfo(title, string.Empty));
            }
            catch (Exception ex)
            {
                TTrace.Error.Send(GetType().FullName, ex.Message + ex.StackTrace);
                TTrace.Error.SendObject("Exception", ex);
                throw;
            }
            return view;
        }
    }
}
Last edited Mar 1 2008 at 8:19 PM  by BillKrat, version 13
Comments
Vardi wrote  May 25 2008 at 10:33 PM  
Hi,
I Build new CAB Visualization that show the WorkItem hierarchy, Worksapce,
SmartPart, Command, Events, State and Items. And Tracing. Cool Tool for SCSF developer...
( http://www.codeplex.com/WorkItemVisualizer )

Updating...
Page view tracker