|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionWPF Commanding offers the base for integration of the GoF Command pattern into an application. This article describes an approach with the following goals:
The attached example demonstrates how to use the Command pattern in an RTF editor: The test project also shows how to unit test a command. The control CommandThe class
Note: This class hierarchy serves only for demonstrating command structures, and is not intended for production level usage of an RTF editor. The implementation of a command class is compact and descriptive, and offers a well defined entry point for analysis in future extension steps: // ------------------------------------------------------------------------
public class EditUndo : EditorCommand
{
// ----------------------------------------------------------------------
public EditUndo( Type ownerType, CommandDescription description ) :
base( "EditUndo", ownerType, description )
{
} // EditUndo
// ----------------------------------------------------------------------
protected override bool OnCanExecute( EditorCommandContext commandContext )
{
if ( !base.OnCanExecute( commandContext ) )
{
return false;
}
return commandContext.TextBox.CanUndo;
} // OnCanExecute
// ----------------------------------------------------------------------
protected override void OnExecute( EditorCommandContext commandContext )
{
commandContext.TextBox.Undo();
} // OnExecute
} // class EditUndo
The class // ------------------------------------------------------------------------
public class IncreaseIndentation : WrapperCommand
{
// ----------------------------------------------------------------------
public IncreaseIndentation( Type ownerType, CommandDescription description ) :
base( EditingCommands.IncreaseIndentation, ownerType, description )
{
} // IncreaseIndentation
// ----------------------------------------------------------------------
protected override bool OnCanExecute( CommandContext commandContext )
{
if ( !base.OnCanExecute( commandContext ) )
{
return false;
}
// add some additional enabling conditions
return true;
} // OnCanExecute
} // class IncreaseIndentation
Command Runtime BehaviourDuring the execution of a command, a command context is created which encapsulates all the runtime parameters. The following diagram documents the runtime behavior:
Creation of a Note: Combining all the runtime values into the class Further down it will be shown how to use the The property UI IntegrationUsing the property Button CommandThe class XAML<Button input:ButtonCommand.Command="{x:Static cmd:RichTextEditorCommands.EditUndo}" />
Code-BehindButton undoButton = new Button();
ButtonCommand.SetCommand( undoButton, RichTextEditorCommands.EditUndo );
Display of the image can be controlled using the class The source of an image is determined by the class
The utility MenuItem CommandUsing the class XAML<Button input:MenuItemCommand.Command="{x:Static cmd:RichTextEditorCommands.EditUndo}" />
Code-BehindMenuItem undoMenuItem = new MenuItem();
MenuItemCommand.SetCommand( undoMenuItem, RichTextEditorCommands.EditUndo );
Display of the image can be controlled using the class The format of the ToolTip is controlled by the class Command RepositoryThe Unit TestWith the basis of the // ----------------------------------------------------------------------
[TestMethod]
public void TestToggleBoldDefault()
{
EditorCommandContext commandContext = CreateCommandContext();
Paragraph firstParagraph = commandContext.Document.Blocks.FirstBlock as Paragraph;
// setup selection
TextRange startContent = new TextRange( commandContext.Document.ContentStart,
commandContext.Document.ContentEnd );
commandContext.Selection.Select( startContent.Start, startContent.End );
commandContext.Selection.ApplyPropertyValue( FlowDocument.FontWeightProperty,
FontWeights.Normal );
string startText = startContent.Text;
// run the command
FontWeight defaultFontWeigth = RichTextEditorCommands.ToggleBold.BoldFontWeight;
RichTextEditorCommands.ToggleBold.Execute( commandContext );
// tests
TextRange endContent = new TextRange( commandContext.Document.ContentStart,
commandContext.Document.ContentEnd );
string endText = endContent.Text;
Assert.AreEqual( startText, endText );
object selectionFontWeight =
commandContext.Selection.GetPropertyValue( FlowDocument.FontWeightProperty );
Assert.AreEqual( defaultFontWeigth, selectionFontWeight );
} // TestToggleBoldDefault
// ----------------------------------------------------------------------
private EditorCommandContext CreateCommandContext()
{
// document
FlowDocument flowDocument = new FlowDocument();
for ( int i = 0; i < 10; i++ )
{
Paragraph paragraph = new Paragraph();
for ( int n = 0; n < 5; n++ )
{
paragraph.Inlines.Add( new Run( "Paragraph Text " +
n.ToString() + " " ) );
}
flowDocument.Blocks.Add( paragraph );
}
// editor
RichTextBox richTextBox = new RichTextBox();
richTextBox.Document = flowDocument;
// command context
return new EditorCommandContext( richTextBox );
} // CreateCommandContext
Custom Command ControlAccording to the description in MSDN, the control UsageTo use the command system, the following approach is suggested:
Points of InterestFurther insights resulting from this article:
History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||