Morse Coder Part 7 : Data Binding User Controls

User controls offer a way to abstract common areas of your User Interface in a reusable package, allowing you to simplify your views and push some of the complexity of your UI into more manageable pieces.  This tutorial will focus on Data Binding to Properties on a User Control from a ViewModel.

Outcome

By the end of this post we should have a basic User Control bound against some Commands living in the MainViewModel to manipulate the content of the Input, in our case, we’ll offer a way to input Morse Code (dots/dashes) outside of needing to use a Keyboard in preparation for extending the App to translate both ways from the User Interface.

Prerequisites

Implementation

We’ll need somewhere for our User Controls to live in the Solution so create a new Folder under the MorseCoder.Shared Project called UserControls.  Create a new UserControl from the Add New Item menu in the new Folder and call it MorseInput.xaml.

User Control Project Structure
User Control Project Structure

I’m thinking of having the User Control stretch the width of the page and displayed underneath the Input TextBox so change the DesignWidth to something more representative, but still workable, 1200.  It doesn’t have to be exact as we’ll be creating the User Control to be scalable and use relative widths.

We should now have a wide User Control containing just a grid.  We’ll want to add in 3 columns to contain a button for dots, dashes, and spaces respectively.  So let’s add that in :

<UserControl x:Class="MorseCoder.UserControls.MorseInput" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MorseCoder.UserControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="1200">

<Grid>
 <Grid.ColumnDefinitions>
 <ColumnDefinition />
 <ColumnDefinition />
 <ColumnDefinition />
 </Grid.ColumnDefinitions>
 <Button Content="dot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="30"/>
 <Button Content="dash" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="30" Grid.Column="1"/>
 <Button Content="space" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="30" Grid.Column="2"/>
 </Grid>
 </UserControl>

Note the Design Width alteration in the UserControl declaration, we’ve added a Grid with 3 columns, each containing a relatively sized Button.

On building the solution you’ll notice that the new User Control appears in the Toolbox :

User Control toolbox
User Control toolbox

We can now add this to the Main Page :

Dot-Dash-Space.png
Dot Dash Space

In order to wire up some commands from our ViewModel on to our Buttons, we’ll need to add some ICommand objects to house the Command, along with some DependencyPropertys to tie up our DataBinding and a PropertyChangedEventHandler to keep our UI in sync.

 

Here’s the code required in the User Control code behind for the dot button:

namespace MorseCoder.UserControls
 {
 public sealed partial class MorseInput : UserControl
 {
 public MorseInput()
 {
 this.InitializeComponent();
 (this.Content as FrameworkElement).DataContext = this;
 }

public ICommand DotCommand
 {
 get { return (ICommand)GetValue(DotCommandProperty); }
 set { SetValueDp(DotCommandProperty, value); }
 }

public static readonly DependencyProperty DotCommandProperty = DependencyProperty.Register("DotCommand", typeof(ICommand), typeof(MorseInput), null);

public event PropertyChangedEventHandler PropertyChanged;

private void SetValueDp(DependencyProperty property, object value, [CallerMemberName] string propertyName = null)
 {
 SetValue(property, value);
 if (PropertyChanged != null)
 {
 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 }
 }
 }
 }

We can now give our user control a name :

<UserControl ... x:Name="MorseInputInstance">

…and add a Command to the Button :

<Button Command="{Binding ElementName=MorseInputInstance, Path=DotCommand}" Content="dot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="30"/>

Note the ElementName referring to the UserControl instance name and the path to the DotCommand Property we just created.

From here on, we can use our MorseInput user control like any other Control.

We’ll need to create a Command on our MainViewModel to perform an action (using the MVVM Light RelayCommand object)  :

public RelayCommand DotCommand { get; private set; }

private void DotCommandAction()
{
Input += ".";
}

…and instantiate it in the Constructor :

DotCommand = new RelayCommand(DotCommandAction);

Finally we can bind the DotCommand object to the DotCommand Property on the MorseInput User Control :

<UserControls:MorseInput DotCommand="{Binding DotCommand}" HorizontalAlignment="Stretch" Margin="50,10" Grid.Row="1" VerticalAlignment="Stretch" />

I’ve filled in the blanks for the other buttons and updated the Solution on GitHub, but to all intents and purposes it’s just more of the above.  In a future post we’ll look at setting the visibility of the control to Hidden dependent on the mode, so that it’s not visible when it’s converting Alphabet to Morse.

Summary

Where are we?

  • We created a User Control allowing us to Bind Commands to properties of controls within the MorseInput control via a set of Dependency Property objects.  This can be extended to bind the button contents displayed, colours etc. and can form the basis of a pattern for a reusable UI.

Where are we heading?

We’ll look at :

  • adding some more functionality to the app to swap the translation direction;
  • methods of serialising POCOs to Application Settings;
  • Messaging between ViewModels using MVVM Light.

4 thoughts on “Morse Coder Part 7 : Data Binding User Controls”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s