Caliburn Micro #003 : Events (Short Hand Syntax)

Previously, We looked at one approach of binding Events to Controls. However, the convention based approach is one of the least used approaches in Caliburn Micro. Think about it, if you need to bind more than one event to the control, say for example, the Click Event and MouseOver Event, this approach would fall short.
Thankfully, Caliburn Micro provides another approach, based on Event Triggers, which solves this problem. While there is a long annotation version of the approach, we would stick to the shorthand version, which is, designed to be more developer friendly.
 
Convention Based Approach
 
Let’s declare a button and assign a OnClick Event to the control using the convention based approach first.
 <Button  x:Name="ClearTextMethod">Clear</Button>

Now, Let’s change the signature to Event Trigger based approach. First, we need to add a namespace in our XAML Headers.

xmlns:cal="http://www.caliburnproject.org"

Event Trigger Based Approach
And now we will attach the event. Notice the change in Syntax.

<Button Content="Clear" cal:Message.Attach="[Event Click] = [Action ClearTextMethod]" />

As mentioned earlier, this approach allows us to attach more events to the Control. If we need to attach a MouseOver Event to the above button, all we need to do is add another pair of [Event][Action] separated by a semi-colon

<Button Content="Clear" cal:Message.Attach="[Event Click] = [Action ClearTextMethod];[Event MouseLeave]=[Action AnotherMethod]" />

Passing Parameter

We could also pass parameters to the method, with the same syntax.

A word of caution though when you pass a boolean parameter to the method. For example, invoking the method with following syntax doesn’t quite work.

<Button Content="Clear" cal:Message.Attach="[Event Click] = [Action ClearTextMethod(true)]" />

The workaround is fairly simple thought, just include a single quote around the string representing True/False. We can modify the syntax as following.

<Button Content="Clear" cal:Message.Attach="[Event Click] = [Action ClearTextMethod('true')]" />

Complete list of tutorials on Caliburn.Micro can be found here

Binding Navigated Event in WebView Control

WebView Control in Xamarin.Form is a highly useful control for displaying a Web Page within your Mobile Application. You can either specify the URI that needs to displayed or you can provide the entire HTML Source to be displayed by assigning an instance of UrlWebViewSource to the Source Property of the control.

From an MVVM point of view, you can bind Source Property of the control to an instance of UrlWebViewSource.
<WebView Source="{Binding GatewayPageSource,Mode=TwoWay}" WidthRequest="500" HeightRequest="500"></WebView>

For Binding the control to an External URI, you could bind your ViewModel Property as follows.


public HtmlWebViewSource GatewayPageSource
 {
 get { return _GateWaySource; }
 set
 {
 SetProperty(ref _GateWaySource, value);
 }
 }

this.GatewayPageSource.BaseUrl = "urlpath";

For Binding the control to an HTML String, you could bind your ViewModel Property as follows.


this.GatewayPageSource.Html = "HtmlString"

One of the caveats however, is that two of the most important Events of the control, namely, Navigating and Navigated, is not Bindable. There are ways to get around this problem though.
The first method that was suggested to me was to use Behavior. I will probably try implementing this in one of later posts. The second approach, was possibly the easiest – create a custom control overriding the WebView and add the required properties.
public class AdvancedWebView : WebView
{
public static readonly BindableProperty NavigatedCommandProperty =
BindableProperty.Create(nameof(NavigatedCommand), typeof(ICommand), typeof(AdvancedWebView), null);

public AdvancedWebView()
{
Navigated += (s, e) =>
{
if (NavigatedCommand?.CanExecute(e) ?? false)
NavigatedCommand.Execute(e);
};
}

public ICommand NavigatedCommand
{
get { return (ICommand)GetValue(NavigatedCommandProperty); }
set { SetValue(NavigatedCommandProperty, value); }
}
}

The XAML with new Control would be as follows


<controls:AdvancedWebView Source="{Binding GatewayPageSource,Mode=TwoWay}"
NavigatedCommand="{Binding WebViewNavigatedCommand}"
WidthRequest="500" HeightRequest="500"/>

For keeping things simple, I have implemented only Navigated Event in the example, however, we could extend this functionality with Navigating Event as well.