Toolbar controls are
containers for a group of commands or controls which are typically related in
their function. ToolBar usually contains buttons which invoke commands.
Toolbar Control
The ToolBar control takes
its name from the bar-like arrangement of buttons or other controls into a
single row or column. WPF ToolBar controls provide an overflow mechanism
which places any items that do not fit naturally within a size-constrained
ToolBar into a special overflow area. Also, WPF ToolBar controls are
usually used with the related ToolBarTray control, which provides special
layout behavior as well as support for user-initiated sizing and arranging of
toolbars.
Specifying the Position of
ToolBars in a ToolBarTray
Use the Band and BandIndex
properties to position the ToolBar in the ToolBarTray. Band indicates the position
in which the ToolBar is placed within its parent ToolBarTray. BandIndex
indicates the order in which the ToolBar is placed within its band. The
following example shows how use this property to place ToolBar controls inside
a ToolBarTray.
Often ToolBar controls contain
more items than can fit into the toolbar's size. When this happens, the ToolBar displays an
overflow button. To see the overflow items, a user clicks the overflow button
and the items are shown in a pop-up window below the ToolBar. The following
graphic shows a ToolBar with overflow
items.
Toolbar with Overflow Items
Code Sample
This code sample given
below will demonstrate how to use Toolbox under MVVM pattern. It will also show
demonstrate to register Commands through ICommand interface.
Below is the application which has toolbar which give following functionality related to an
email message new, open, save, cut, copy, paste and other operations.
Below are is XAML code of
above UI. It contains ToolBarTray and ToolBars with Band and BandIndex values.
Also we have shown how to show Overflow items.
<Window x:Class="WPFToolBarExample.MainWindow"
Title="MainWindow"
Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToolBarTray Background="White"
FlowDirection="LeftToRight"
Grid.Row="0">
<ToolBar Band="1"
BandIndex="1" >
<Button Margin="2" Command="{Binding NewFileCommand}">
<Image Source="Images/Document.png" Stretch="None" ToolTipService.ToolTip="New
Document"/>
</Button>
<Button Margin="2" Command="{Binding OpenNewFileCommand}">
<Image Source="Images/Folder.png" Stretch="None" ToolTipService.ToolTip="New
Folder"/>
</Button>
<Button Margin="2"
Command="{Binding SaveCommand}"
CommandParameter="MyDocument.Txt"
ToolTipService.ShowOnDisabled="True"
ToolTipService.ToolTip="Save">
<Button.Content>
<Viewbox Height="16" Width="16">
<Image Stretch="None">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Images/Save.png"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source" Value="Images/SaveDisabled.png"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Viewbox>
</Button.Content>
</Button>
<Button Margin="2" Command="{Binding ClearCommand}">
<Image Source="Images/Delete.png" Stretch="None" ToolTipService.ToolTip="Delete"/>
</Button>
</ToolBar>
<ToolBar Band="2"
BandIndex="1"
VerticalContentAlignment="Stretch"
HorizontalAlignment="Left" Width="76">
<Button Margin="2" Command="{Binding PrintCommand}">
<Image Source="Images/Printer.png" Stretch="None" ToolTipService.ToolTip="Print"/>
</Button>
<Button Margin="2">
<Image Source="Images/Status
Flag Red.png" Stretch="None"
ToolTipService.ToolTip="Status"/>
</Button>
</ToolBar>
<ToolBar Band="3"
BandIndex="1">
<Button Margin="2">
<Image Source="Images/Copy.png" Stretch="None" ToolTipService.ToolTip="Copy"/>
</Button>
<Button Margin="2">
<Image Source="Images/Paste.png" Stretch="None" ToolTipService.ToolTip="Paste"/>
</Button>
<Button Margin="2">
<Image Source="Images/Cut.png" Stretch="None" ToolTipService.ToolTip="Cut"/>
</Button>
<Separator/>
<ToggleButton Margin="2">
<Image Source="Images/Format
Font Larger.png" Stretch="None" />
</ToggleButton>
<ToggleButton Margin="2">
<Image Source="Images/Format
Stylized Text.png" Stretch="None"
ToolTipService.ToolTip="Bold"/>
</ToggleButton>
<ToggleButton Margin="2">
<Image Source="Images/Format
Underline.png" Stretch="None"
ToolTipService.ToolTip="Underline"/>
</ToggleButton>
<Separator/>
<RadioButton Margin="2" ToolBar.OverflowMode="Always">
<Image Source="Images/Format
Align Left.png" Stretch="None"
ToolTipService.ToolTip="Align Left"/>
</RadioButton>
<RadioButton Margin="2" ToolBar.OverflowMode="Always">
<Image Source="Images/Format
Align Center.png" Stretch="None"
ToolTipService.ToolTip="Align
Center"/>
</RadioButton>
<RadioButton Margin="2" ToolBar.OverflowMode="Always">
<Image Source="Images/Format
Align Right.png" Stretch="None"
ToolTipService.ToolTip="Align
Right"/>
</RadioButton>
</ToolBar>
</ToolBarTray>
<TextBox AcceptsReturn="True"
Grid.Row="1"
x:Name="textInput"
BorderThickness="0"
Foreground="#FF767676"
MinHeight="140"
Text="{Binding DisplayText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
/>
</Grid>
</Window>
|
Commands
To implement backend
functionality for ToolBar items under MVVM design we need to implement commands
for each functionality.
What is a Command?
A Command is an object
that is bound to. It provides a separation between a user interface and
logic.
|
This is the core concept.
In a bit more detail we can describe a command as follows:
- A command is an object that implements the ICommand interface.
- Generally, it is associated with a function in some code.
- User interface elements bind to commands - when they are activated by the user the command is fired - which calls the associated function.
- Commands know if they are enabled or not.
- A function can disable the command object - automatically disabling any user interface elements associated with it.
Actually, there's a whole
lot more to Commands. We can use commands to deal with asynchronous
functionality, to provide logic that can be tested with or without a user
interface, and more.
To make things easy, I have
created a RelayCommand class implemented ICommand interface. We will use
RelayCommands to register our commands with CommandManager.
RelayCommand Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WPFToolBarExample.Helper
{
/// <summary>
/// To
register commands in MMVM pattern
/// </summary>
public
class
RelayCommand : ICommand
{
readonly
Action<object> _execute;
readonly
Predicate<object> _canExecute;
/// <summary>
///
Constructer takes Execute events to register in CommandManager.
/// </summary>
/// <param name="execute">Execute method as action.</param>
public
RelayCommand(Action<object> execute)
: this(execute,
null)
{
try
{
if (null == execute)
{
throw
new NotImplementedException("Not implemented");
}
_execute = execute;
}
catch
(Exception)
{
throw;
}
}
/// <summary>
///
Constructer takes Execute and CanExcecute events to register in
CommandManager.
/// </summary>
/// <param name="execute">Execute method as action.</param>
/// <param name="canExecute">CanExecute method as return bool type.</param>
public
RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
try
{
if (null == execute)
{
_execute = null;
throw
new NotImplementedException("Not implemented");
}
_execute = execute;
_canExecute = canExecute;
}
catch
(Exception)
{
}
}
/// <summary>
/// Can
Executed Changed Event
/// </summary>
public
event
EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
/// <summary>
///
Execute method.
/// </summary>
/// <param name="parameter">Method paramenter.</param>
public
void
Execute(object
parameter)
{
_execute(parameter);
}
/// <summary>
///
CanExecute method.
/// </summary>
/// <param name="parameter">Method paramenter.</param>
/// <returns>Return
true if can execute.</returns>
public
bool
CanExecute(object parameter)
{
return
_canExecute == null ? true : _canExecute(parameter);
}
}
}
|
Creating Command
Here are the steps to
create a command for UI control.
·
Create Execute command method.
·
Create CanExecute command method.
·
Create ICommand Property.
·
Register both command methods through RelayCommand class.
·
Return registered command through Property.
·
Bind property with Control’s Command property.
Below is the code how to
create command property using steps mentioned above.
ICommand _saveCommand;
public
ICommand
SaveCommand
{
get
{
if (null == this._saveCommand)
//Register command with RelayCommand
class.
this._saveCommand
= new RelayCommand(param
=> this.SaveCommand_Execute(param),
param => this.SaveCommand_CanExecute(param));
return
_saveCommand;
}
}
bool
SaveCommand_CanExecute(object param)
{
if (string.IsNullOrEmpty(this.DisplayText))
return
false;
return
true;
}
void
SaveCommand_Execute(object param)
{
//Do some save coding.
MessageBox.Show("You have
sent '" + param.ToString() + "' as command parameter to save this
document.");
}
|
View Model
We have created View Model
that will contain Commands. And properties bound with UI controls.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using WPFToolBarExample.Helper;
namespace WPFToolBarExample.ViewModel
{
class
ApplicationUIViewModel : BaseViewModel
{
string
_displayText = string.Empty;
public
string
DisplayText
{
get { return _displayText; }
set
{
_displayText = value;
OnPropertyChanged(() => this.DisplayText);
}
}
public
ApplicationUIViewModel()
{
this.DisplayText
= "Hi Team, " + "\n" + "\nI will be out of
office for a week." + "\n" + "\nRegards,"
+ "\n" + "\n Siddharth
Mishra";
}
#region Commands
ICommand
_newFileCommand;
public
ICommand
NewFileCommand
{
get
{
if
(_newFileCommand == null)
this._newFileCommand
= new RelayCommand(param
=> this.NewFileCommand_Execute(param),
param => this.NewFileCommand_CanExecute(param));
return
_newFileCommand;
}
}
bool
NewFileCommand_CanExecute(object param)
{
return
true;
}
void
NewFileCommand_Execute(object param)
{
this.DisplayText
= string.Empty;
}
ICommand
_openNewFileCommand;
public
ICommand
OpenNewFileCommand
{
get
{
if (this._openNewFileCommand
== null)
this._openNewFileCommand
= new RelayCommand(param
=> this.OpenNewFileCommand_Execute(param),
param => this.OpenNewFileCommand_CanExecute(param));
return
_openNewFileCommand;
}
}
bool
OpenNewFileCommand_CanExecute(object param)
{
return
true;
}
void
OpenNewFileCommand_Execute(object param)
{
string
initialDir = string.Empty;
if (null != param)
initialDir = param.ToString();
var
dialog = new OpenFileDialog();
dialog.Filter = "TXT files
(*.TXT)|*.TXT";
dialog.FilterIndex = 1;
dialog.Title = "Please select a
text file..";
dialog.InitialDirectory = string.IsNullOrEmpty(initialDir) ? Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
: initialDir;
DialogResult result = dialog.ShowDialog();
}
ICommand
_saveCommand;
public
ICommand
SaveCommand
{
get
{
if (null == this._saveCommand)
//Register command with RelayCommand
class.
this._saveCommand
= new RelayCommand(param
=> this.SaveCommand_Execute(param),
param => this.SaveCommand_CanExecute(param));
return
_saveCommand;
}
}
bool
SaveCommand_CanExecute(object param)
{
if (string.IsNullOrEmpty(this.DisplayText))
return
false;
return
true;
}
void
SaveCommand_Execute(object param)
{
//Do some save coding.
MessageBox.Show("You have
sent '" + param.ToString() + "' as command parameter to save this
document.");
}
#endregion
}
}
|
Registering ViewModel with
UI data context.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPFToolBarExample.ViewModel;
namespace WPFToolBarExample
{
/// <summary>
///
Interaction logic for MainWindow.xaml
/// </summary>
public
partial
class
MainWindow : Window
{
public
MainWindow()
{
InitializeComponent();
this.Loaded
+= MainWindow_Loaded;
}
void
MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ApplicationUIViewModel appVM = new ApplicationUIViewModel();
this.DataContext
= appVM;
}
}
}
|
Above application is a
simple demonstration of MVVM pattern with Commands and Toolbar implementation.