Commands

Introduction

Xamarin, and the Rock Mobile application shell, use a concept called Commands to handle most actions and events. When you tap a button, it executes a Command. These are usually available through a Command property, though sometimes a view might support multiple different commands in which case the names will vary. Additionally, each Command can take a single parameter to provide additional details about how it should perform it's task.

Since all these Commands implement the same structure, this means you can use any command anywhere. So just like you can setup a button to open a browser window, you can also use that same command and tie it to a swipe gesture so if the user swipes on the screen it also opens a browser window.

Further down you will find descriptions about the various commands available, but before that you probably want to see a quick example of how to actually use commands. First, lets look at a simple button that we want to open up a browser window when the user taps on it.

<StackLayout>
    <Button Text="Search"
            StyleClass="btn, btn-primary"
            Command="{Binding OpenBrowser}"
            CommandParameter="https://www.google.com/search?q=rockrms" />
</StackLayout>

What we are doing is binding the Command parameter of the button to the OpenBrowser handler built into all blocks. Next we are passing the URL to open via the CommandParameter. Now, lets say we want to be able to have a textbox on screen for the user to put in a search term and then use that as the search term for Google to use.

<StackLayout>
    <Rock:FieldContainer>
        <Rock:TextBox Label="Search" x:Name="SearchTerm" />
    </Rock:FieldContainer>

    <Button Text="Search"
            StyleClass="btn, btn-primary"
            Command="{Binding OpenBrowser}"
            CommandParameter="https://www.google.com/search?q=rockrms" />
</StackLayout>

Okay, that renders a nice text box but our search button is still using the hard coded URL. To fix that we are going to change the button definition so we can create a special object as the CommandParameter:

<StackLayout>
    <Rock:FieldContainer>
        <Rock:TextBox Label="Search" x:Name="SearchTerm" />
    </Rock:FieldContainer>

    <Button Text="Search"
            StyleClass="btn, btn-primary"
            Command="{Binding OpenBrowser}">
        <Button.CommandParameter>
            <Rock:OpenBrowserParameters Url="https://www.google.com/search">
                <Rock:Parameter Name="q"
                                Value="{Binding Path=Text, Source={x:Reference SearchTerm}}" />
            </Rock:Action>
        </Button.CommandParameter>
    </Button>
</StackLayout>

So what we did above is create an inline object in XAML and place it inside the Button's CommandParameter property. This object is the <Rock:OpenBrowserParameters>...</Rock:OpenBrowserParameters> object. It specifies what we are going to do in the command, specifically, the Url in this case is the base URL to go to. Contained inside is a number of parameter values that will be passed as query string parameters.

We have defined a parameter called q which is what Google uses for the search term. For the value, you can enter a static value if you wish, but we wanted a dynamic one. So we used XAML binding to reference the text box's value. {Binding Source={x:Reference SearchTerm}, Path=Text} means: Take the value from the object whose name is SearchTerm and use the property found at the path Text. Note: The reason it's called Path is because you can specify a property path (e.x. Text.Length) that will process a tree of properties.

So, what we have finally achieved is a Search button that uses a textbox on screen to collect the user input and then go to a search results page - and we did it without a single line of code!

It's worth being aware that most commands support a short form of their CommandParameter. You saw this above with the OpenBrowser command. If you don't need to pass any custom parameters and just need to specify a static URL, you can just pass the URL string into the CommandParameter itself. Each command will note what forms the CommandParameter can take.

Most of the commands will work in the context of a block's content (the one exception is the Callback command, that only works inside a block that derives from the Content block). Many of them will work outside the context of a block as well. For example, in the flyout menu. However, some do require knowing what page you are on and thus will not work in that context. One example of this is the ShowActionPanel command. It needs to know what page to display the action panel over and if used from the flyout menu that context is not available to it.

Shorthand

All of the command parameter objects discussed in this section support being used as a XAML extension. Said another way, there is a shorthand to creating them. This shorthand does not work if you need to pass an array of items into the parameters (such as a bunch of query string parameters), but it does work for other use cases. Let's compare a "standard" usage as follows.

<Button Text="Scroll"
        Command="{Binding ScrollToVisible}">
    <Button.CommandParameter>
        <Rock:ScrollToVisibleParameters Anchor="{x:Reference myLabel}"
                                        Position="Start" />
    </Button.CommandParameter>
</Button>

This is a rather verbose way to do it, but it allows us to pass in a whole POCO class of ScrollToVisibleParameters that then specifies the anchor element to be made visible and where to place it after scrolling. This can be shortened using XAML extensions to the following.

<Button Text="Scroll"
        Command="{Binding ScrollToVisible}"
        CommandParameter="{Rock:ScrollToVisibleParameters Anchor={x:Reference myLabel}, Position=Start}" />

As you can see, this is much more succinct. Though again, it does not work when you need to supply an array of elements as a property. Do notice that the syntax changes ever so slightly for setting properties inside the shorthand syntax. First, the properties are separated by a comma. Second, the property values are not enclosed in quotation marks (since we are already inside a quotation for the outer property).

Because of this slightly different syntax there are some things to know. If your value is going to contain a comma, then you need to enclose it in single quotes, inside the double quotes of the outer property as shown below.

<Button Text="Send"
        Command="{Binding SendSms}"
        CommandParameter="{SendSmsParameters Message='Hello, Dave.' Recipients=1558881234}" />

You should be familiar with the Parameter element before reading further about commands.

Binding Context

Bindings can get quite complicated when they are nested within action items such as ShowCoverSheet, ShowActionPanel, and ShowPopup. You may experience issues where commands do not function when they are nested, but understand this is not a bug, but rather a designed behavior by Xamarin.Forms.

In order to retain functionality when applying bindings deeper in a hierarchy of commands, the addition of BindingContext. is required. Below is an example of a button that opens an action panel. The action panel houses a single option that carries out multiple actions and requires BindingContext to do so.

<Button x:Name="BindingContext" 
        Text="Action Panel With Aggregate Bindings"
        Command="{Binding ShowActionPanel}">
            
        <Button.CommandParameter>
            <Rock:ShowActionPanelParameters Title="Action Panel Bindings"
                                            CancelTitle="Cancel">
                
                <Rock:ActionPanelButton Title="AggregateCommand"
                                        Command="{Binding BindingContext.AggregateCommand, Source={x:Reference Name=BindingContext}}">
                    
                    <Rock:ActionPanelButton.CommandParameter>
                        <Rock:AggregateCommandParameters>
                            <Rock:CommandReference Command="{Binding BindingContext.ShowToast, Source={x:Reference Name=BindingContext}}"
                                                    CommandParameter="Successful binding implementation" />
                                
                                                                
                            <Rock:CommandReference Command="{Binding BindingContext.PushPage, Source={x:Reference Name=BindingContext}}"
                                                    CommandParameter="2cda9cfc-4717-4455-bfc2-633735cda86f" />
                        </Rock:AggregateCommandParameters>
                    </Rock:ActionPanelButton.CommandParameter>
                </Rock:ActionPanelButton>
            </Rock:ShowActionPanelParameters>
        </Button.CommandParameter>
</Button>

Last updated

⚙️ Powered by Rock RMS