0
votes

I am new to Xamarin Form Application development and Want to try a simple app that will get string from textfield and place it in label by data binding. enter image description here

  1. Text field with 20 px margin from both side and vertically center.
  2. Label will be below text field.
  3. When typing in textField, the label will update (MVVM)
  4. UI design will be from XAML.

Thank you.

2

2 Answers

1
votes

If you are using Xamarin Forms to achieve this and using DataBinding (MVVM), first in your ViewModel (We will call it MainPageViewModel.cs) you need something like this:

using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace SandboxForms.ViewModels
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private string _myTextField;
        public string MyTextField
        {
            get { return _myTextField; }
            set
            {
                _myTextField = value;
                OnPropertyChanged(nameof(MyTextField));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Then in our ContentPage (We will call this one MainPage.xaml):

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
        xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
        x:Class="SandboxForms.Pages.MainPage"
        xmlns:viewmodels="clr-namespace:SandboxForms.ViewModels;SandboxForms">
    <ContentPage.BindingContext>
        <viewmodels:MainPageViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout Padding="20">
            <!-- I am applying EndAndExpand to the entry and 
            StartAndExpand to the label to center them each other -->
            <Entry 
                HorizontalOptions="FillAndExpand"
                VerticalOptions="EndAndExpand"
                Placeholder="Write here and see the magic!!!"
                Text="{Binding MyTextField}"/>
            <Label 
                HorizontalTextAlignment="End"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="StartAndExpand"
                Text="{Binding MyTextField}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Here is a few screenshots of the results: Application starting, Entering text on your Entry Hope this works for you, my best regards!

0
votes

There are two approaches for data binding each of which has merits depending on the situation. The first is MVVM as mentioned previously. This works well for fields that your ViewModel should know about, such as the text in an entry field but this isn't always the case and it's important to have a complete understanding before choosing the right method for your needs.

MVVM Approach

ViewModel

public class MyPageViewModel : INotifyPropertyChanged
{
    private string myTextField;
    public string MyTextField
    {
        get { return myTextField; }
        set
        {
            if( !myTextField.Equals( value ) )
            {
                myTextField = value;
                OnPropertyChanged("MyTextField");
            }
        }
    }
}

View

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
        xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
        x:Class="SandboxForms.Pages.MainPage"
        xmlns:viewmodels="clr-namespace:SandboxForms.ViewModels;SandboxForms">
    <ContentPage.BindingContext>
        <viewmodels:MainPageViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout Padding="20">
            <!-- I am applying EndAndExpand to the entry and 
            StartAndExpand to the label to center them each other -->
            <Entry 
                HorizontalOptions="FillAndExpand"
                VerticalOptions="EndAndExpand"
                Placeholder="Write here and see the magic!!!"
                Text="{Binding MyTextField}"/>
            <Label 
                HorizontalTextAlignment="End"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="StartAndExpand"
                Text="{Binding MyTextField}"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

This is generally a preferred approach by most developers as opposed to mixing business logic directly in the code behind of your UI.

There are a number of helpers, and frameworks out there that you can look at if you aren't familiar with this. The following are some of the more popular ones.

  1. MvvmHelpers - James Montemagno
  2. Prism Library (my personal favorite)
  3. Mvvm Cross
  4. Mvvm Light

View Centric Approach

Sometimes it actually would violate the MVVM pattern to directly bind to a property of our ViewModel, and other times we may want to display something in our View without the need of updating a backing field in the ViewModel. As an example we can look at Xamarin's guide to data binding.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderBindingsPage"
             Title="Slider Bindings Page">

  <StackLayout>
    <Label Text="ROTATION"
           BindingContext="{x:Reference Name=slider}"
           Rotation="{Binding Path=Value}"
           FontAttributes="Bold"
           FontSize="Large"
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />

    <Slider x:Name="slider"
            Maximum="360"
            VerticalOptions="CenterAndExpand" />

    <Label BindingContext="{x:Reference slider}"
          Text="{Binding Value,
                          StringFormat='The angle is {0:F0} degrees'}"
          FontAttributes="Bold"
          FontSize="Large"
          HorizontalOptions="Center"
          VerticalOptions="CenterAndExpand" />
  </StackLayout>
</ContentPage>

I should note that one of the most common times I would recommend using this approach is with Context Actions in a ListView, since our ViewModel may contain the Command that we want to execute on the individual cell, however the cell in which we are executing the context action actually is bound to the object from our IEnumerable<T> and not our ViewModel. In this particular case we would do something like the following:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns ="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Name="someListPage"
             x:Class="MyApp.Views.SomeListPage">
  <ListView ItemsSource="{Binding Gear}" 
            CachingStrategy="RecycleElement"
            IsRefreshing="{Binding IsRefreshing}"
            IsPullToRefreshEnabled="True"
            RefreshCommand="{Binding RefreshCommand}">
    <ListView.ItemTemplate>
      <DataTemplate>
        <TextCell Text="{Binding Description}" Detail="{Binding Detail}">
          <TextCell.ContextActions>
            <MenuItem Text="Remove"
                      Command="{Binding BindingContext.RemoveItemCommand,Source={x:Reference someListPage}}"
                      CommandParameter="{Binding .}"
                      IsDestructive="True" />
          </TextCell.ContextActions>
        </TextCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

You'll notice that for this to work we first give the page itself a name that we can then reference for our binding for the ContextAction Command property. This is only changing where we are looking for this single property. We then resume using the normal binding context for the CommandParameter property and pass in the actual object the cell is bound to with {Binding .}

Hope this helps you better understand your options for binding with Xaml. Happy Coding!