Use Case
| • | You want to create a user interface component that can be used/reused in different contexts. |
Relevant Architecture
Relevant Types
| • | IApplicationComponent |
| • | IApplicationComponentView |
| • | IApplicationComponentHost |
| • | ApplicationComponent |
| • | AssociateViewAttribute |
Sample Code
using System;
using System.IO;
using System.Windows.Forms;
using ClearCanvas.Common;
using ClearCanvas.Desktop;
using ClearCanvas.Desktop.Actions;
using ClearCanvas.Desktop.Tools;
using ClearCanvas.Desktop.View.WinForms;
namespace MyPlugin.TextEditor
{
[ExtensionPoint()]
public class TextEditorComponentViewExtensionPoint : ExtensionPoint<IApplicationComponentView> {}
[AssociateView(typeof (TextEditorComponentViewExtensionPoint))]
public class TextEditorComponent : ApplicationComponent
{
private string _filename;
private string _text;
private int _wordCount;
public TextEditorComponent()
{
}
public string Filename
{
get { return _filename; }
set
{
_filename = value;
this.Modified = true;
}
}
public string Text
{
get { return _text; }
set
{
_text = value;
this.Modified = true;
UpdateWordCount();
}
}
public int WordCount
{
get { return _wordCount; }
private set
{
_wordCount = value;
NotifyPropertyChanged("WordCount");
}
}
public void Save()
{
File.WriteAllText(_filename, _text);
this.Exit(ApplicationComponentExitCode.Accepted);
}
public void Cancel()
{
this.Exit(ApplicationComponentExitCode.None);
}
private void UpdateWordCount()
{
// really simple algorithm to count words for illustrative purposes only
// by assuming spaces, period, comma, or (semi)colon between words
char[] wordSeparators = new char[] {' ', '.', ',', ';', ':'};
int wordCount = this.Text.Split(wordSeparators, StringSplitOptions.RemoveEmptyEntries).Length;
this.WordCount = wordCount;
}
}
[ExtensionOf(typeof (TextEditorComponentViewExtensionPoint))]
public class TextEditorComponentView : WinFormsView,
IApplicationComponentView
{
private TextEditorComponent _component;
private TextEditorControl _control;
public void SetComponent(IApplicationComponent component)
{
_component = (TextEditorComponent) component;
}
public override object GuiElement
{
get
{
if (_control == null)
{
_control = new TextEditorControl(_component);
}
return _control;
}
}
}
public partial class TextEditorControl : UserControl
{
private readonly TextEditorComponent _component;
public TextEditorControl(TextEditorComponent component)
{
InitializeComponent();
_component = component;
_txtText.DataBindings.Add("Text", _component,
"Text", true,
DataSourceUpdateMode.OnPropertyChanged);
_txtFilename.DataBindings.Add("Text", _component,
"Filename", true,
DataSourceUpdateMode.OnPropertyChanged);
_txtWordCount.DataBindings.Add("Text", _component,
"WordCount", true,
DataSourceUpdateMode.OnPropertyChanged);
_btnSave.Click += delegate(object sender, EventArgs args) { _component.Save(); };
_btnCancel.Click += delegate(object sender, EventArgs args) { _component.Cancel(); };
}
}
}
Remarks
The sample code above is a compilation of snippets in the section Designing an Application Component.
There are a few important things to note about Application Components:
| • | Application Components can be hosted in different containers, such as Shelves, Workspaces or Dialogs. This allows for flexible reuse. |
| • | The View layer is thin and contains no business logic. This pattern, known as Presentation Model, allows a new View to be written with the least possible effort. Note that this was done, not out of a desire for architectural purity, but because we anticipate that we will be supporting Windows Presentation Foundation in the future. |
| • | Typically, the Application Component and its View are contained in separate plugins, allowing a new View to be swapped in without having to recompile the component itself. |
Using the Wizard
The ClearCanvas SDK provides some useful wizards to make common tasks a little easier. One such task is creating an application component. To use the wizard to create an application component:
| 1. | Create a new ClearCanvas plugin, or select an existing plugin in which to host the component. |
| 2. | Add references to ClearCanvas.Desktop.dll and ClearCanvas.Common.dll if they haven't already been added. |
| 3. | Create a new ClearCanvas WinForms View plugin, or select an existing View plugin in which to host the View. |
| 4. | Add references to ClearCanvas.Desktop.dll, ClearCanvas.Desktop.View.WinForms, ClearCanvas.Common.dll (if they haven't already been added) and the assembly that contains the Application Component itself. |
| 5. | Bring up the Add New Item dialog (right click on the project, then select Add followed by New Item). |
| 6. | Under My Templates, select ClearCanvas Application Component. Name the component appropriately and click OK. |

| 7. | On the ClearCanvas Application Component Wizard that appears, ensure that the proper View assembly has been selected (i.e., the one created or selected in Step 3 above) and click OK. This will generate the appropriate boilerplate code in both the Model and View plugins. |

| 8. | Design your component. |
| 9. | Compile the project and copy the resulting assemblies into the /plugins directory of your ClearCanvas Workstation installation. |
Examples in Code Base
| • | ClearCanvas.ImageViewer.Explorer.Dicom.SearchPanelComponent |
| • | ClearCanvas.ImageViewer.Explorer.Dicom.View.WinForms.SearchPanelComponentView |
| • | ClearCanvas.ImageViewer.Explorer.Dicom.View.WinForms.SearchPanelComponentControl |