Exercise 5: Send notifications to the renderer and the element
In this exercise, you'll send notifications to and from the renderer and the shared code without tightly coupling the element and the renderer.

To complete the exercise, you will need Visual Studio for Windows or macOS with the Xamarin development tools installed. You will also need either an emulator/simulator or a device to run the exercise on. Please see the setup page if you need help installing the Xamarin development environment.
Open the starter solution
Open the starter solution from the Exercise 5 > Start folder in your copy of the cloned or downloaded course materials in either Visual Studio on Windows or Visual Studio for Mac.
If you're using Visual Studio on Windows, you'll see all of the platform or head projects: iOS, Android and Windows. If you're using macOS, the Windows projects will be disabled (grayed out).
Send a message from the element
You want to clear your drawing surface when the user taps the clear/delete button. However, you don't want to hold a reference from the element to the renderer, so you'll send a notification using the built-in Messaging Center.
- Open SketchView.cs in the shared project.
- Create a public method named Clear.
-
Call
MessagingCenter.Send
, with a message of "Clear".public void Clear () { MessagingCenter.Send(this, "Clear"); }
- Open MainPage.xaml.cs.
-
In the
OnClearClicked
method, call the new Clear method on sketchView.
Subscribe to the message in the renderer
The following steps should be performed in each platform-specific project you wish to support.
- Open SketchViewRenderer.cs
-
Create a new void method named OnMessageClear that accepts a
SketchView
parameter named sender. This method will be called when the clear message is received. -
You want to ensure you only respond to messages from the element associated to this instance of the renderer. Check if sender matches
Element
. If it does, call theClear
method on Control.void OnMessageClear(SketchView sender) { if (sender == Element) Control.Clear(); }
-
Go to the
OnElementChanged
method. -
After the native control is assigned, call
MessagingCenter.Subscribe
to subscribe to the clear message and setOnMessageClear
to theAction
callback. -
To clean up your code, override
Dispose
andUnsubscribe
from these messages. - Run the application, draw, and then tap the clear button.
protected override void OnElementChanged(ElementChangedEventArgs e)
{
if (Control == null)
{
...
MessagingCenter.Subscribe<SketchView>(this, "Clear", OnMessageClear);
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
MessagingCenter.Unsubscribe<SketchView>(this, "Clear");
}
base.Dispose(disposing);
}
Create a controller interface
Next you're going to send a notification from the platform-specific renderers to the Xamarin.Forms sketch view element. To do this you're going to add a public method on the element. However you only want to raise it from the renderer. To reduce discoverability, you're going to define the method within an interface and explicitly implement it.
- In the XFDraw shared project, create a new interface named ISketchController.
-
Add a
void
method named SendSketchUpdated that accepts no arguments.
public interface ISketchController
{
void SendSketchUpdated();
}
Implement the controller interface
To notify the shared code, you'll create and raise a public event.
- Open SketchView.cs in the shared project.
- Explicitly implement
ISketchController
. - Add a new public event handler named SketchUpdated.
- In the
SendSketchUpdated
, invoke the SketchUpdated event.
class SketchView : View, ISketchController
{
...
public event EventHandler SketchUpdated;
void ISketchController.SendSketchUpdated()
{
if(SketchUpdated != null)
SketchUpdated(this, EventArgs.Empty);
}
}
Notify the element
The following steps should be completed in each platform-specific project.
-
Open SketchViewRender.cs and find the
OnElementChanged
method. -
When the native control has been instantiated, subscribe to its
LineDrawn
event; create a handler method named PaintViewLineDrawn. -
In the
PaintViewLineDrawn
handler method, cast Element toISketchController
and call the explicitly definedSendSketchUpdated
method.
protected override void OnElementChanged(ElementChangedEventArgs e)
{
...
paintView.LineDrawn += PaintViewLineDrawn;
}
private void PaintViewLineDrawn(object sender, System.EventArgs e)
{
var sketchCon = (ISketchController)Element;
if (sketchCon == null)
return;
sketchCon.SendSketchUpdated();
}
Subscribe to the event
The final step is to subscribe to the event on the SketchView in the shared code. You'll use the event to disable the clear button if the drawing surface is blank. To control the enabled state of the ToolbarItem, you need to use a Command. If you're familiar with commands you can implement this on your own, or use the code provided. Add the code below to MainPage.xaml.cs in the shared project:
-
Create a boolean property named IsCanvasDirty with a backing field to track the state of the canvas. Define the command and call
ChangeCanExecute
on the command when the IsCanvasDirty property is updated.public partial class MainPage : ContentPage { bool IsCanvasDirty { get { return isCanvasDirty; } set { isCanvasDirty = value; if (clearCommand != null) clearCommand.ChangeCanExecute(); } } bool isCanvasDirty; Command clearCommand; ... }
-
Subscribe to the
SketchUpdated
event and instantiate clearCommand. Assign the new command to the trash tool bar item. The command is replacing the event handler; delete theClicked
subscription.public MainPage() { ... sketchView.SketchUpdated += OnSketchUpdated; clearCommand = new Command(OnClearClicked, () => { return IsCanvasDirty; }); var trash = new ToolbarItem() { Text = "Clear", Icon = "trash.png", Command = clearCommand }; ... }
-
In the constructor, subscribe to sketchView's SketchUpdated event with an event handler method named OnSketchUpdated. When OnSketchUpdated is called, set IsCanvasDirty to true. When OnClearClicked is called, call sketchView.Clear and set IsCanvasDirty to false.
public MainPage() { ... sketchView.SketchUpdated += OnSketchUpdated; } void OnSketchUpdated(object sender, EventArgs e) { IsCanvasDirty = true; } void OnClearClicked () { sketchView.Clear(); IsCanvasDirty = false; }
- Run the application.
Exercise summary
In this exercise you sent notifications between the shared element and platform-specific renderers without tightly coupling the renderer instance to the element. Specifically, you'll notify the platform-specific code to clear the drawing surface from the shared UI and you'll notify the shared code when the drawing surface is updated.
You can view the completed solution in the Exercise 5 > Completed folder of your copy of the cloned or downloaded course materials.