The MVVM pattern becomes far more powerful once you wire up commands, yet Silverlight 4 does not ship with a built-in ICommand implementation. The snippet below shows a minimal, self-contained approach that avoids external toolkits.
Step 1 – Craft a reusable command object
Create a class that fulfills ICommand by forwarding calls to two delegates: one for execution and one for the optional "can-execute" guard.
public sealed class SimpleCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public SimpleCommand(Action<object> execute, Predicate<object> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => _execute(parameter);
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
Step 2 – Expose a command from the ViewModel
Add a public read-only property typed as ICommand. The view will bind to this member.
public ICommand RefreshCommand { get; private set; }
Step 3 – Instantiate the command
In the ViewModel constructor, hook the delegates to real methods (or lambdas).
RefreshCommand = new SimpleCommand(OnRefreshRequested, CanRefresh);
Step 4 – Make the ViewModel discoverable
Expose the ViewModel through XAML so the designer can see it. A common trick is to declare it as a resource.
<UserControl.Resources>
<local:MainViewModel x:Key="MainVM" />
</UserControl.Resources>
Step 5 – Bind the UI element
Any control that implements ICommandSource (Button, HyperlinkButton, etc.) can now bind to the command. Use CommandParameter to pipe data from the view.
<Button Content="Refresh"
Width="120"
Command="{Binding RefreshCommand}"
CommandParameter="{Binding ElementName=FilterBox, Path=Text}" />
After these five steps, the button automatically enables or disables itself and triggers the ViewModel logic without any code-behind.
Complete ViewModel sample
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
AllItems = new ObservableCollection<Item>
{
new Item { Id = 1, Name = "Apple" },
new Item { Id = 2, Name = "Orange" },
new Item { Id = 3, Name = "Banana" },
new Item { Id = 4, Name = "Pear" }
};
FilteredItems = new ObservableCollection<Item>();
RefreshCommand = new SimpleCommand(Refresh, CanRefresh);
}
public ICommand RefreshCommand { get; }
public ObservableCollection<Item> AllItems { get; }
public ObservableCollection<Item> FilteredItems { get; }
private void Refresh(object parameter)
{
var text = parameter as string ?? string.Empty;
FilteredItems.Clear();
foreach (var item in AllItems.Where(i => i.Name.StartsWith(text, StringComparison.OrdinalIgnoreCase)))
FilteredItems.Add(item);
}
private bool CanRefresh(object parameter) => true;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string property = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public sealed class Item
{
public int Id { get; set; }
public string Name { get; set; }
}