This is a migrated thread and some comments may be shown as answers.

two way data binding example

1 Answer 519 Views
DataForm
This is a migrated thread and some comments may be shown as answers.
Sadanan
Top achievements
Rank 1
Sadanan asked on 13 Aug 2019, 07:07 PM

With the two-way data binding when the source properties are updated outside of the control, they are still kept in sync with the DataForm editors, enabling you to solve a wide-range of scenarios.

Above feature is described in Dataform product page however I dont see any example in QSF or SDK Browser, as how two way source binding actually works and what scenarios it can solve. 

In my scenario, once dataform has been rendered can I use two way binding to update Dataform when my Source model gets updated from async API call.  It would be helpful to see an example for everyone so posting here. 


1 Answer, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 13 Aug 2019, 10:08 PM

Hi Sadanan,

There is nothing special you need to do, it supports it without any configuration. The two-way binding description refers to how we handle the editor's properties internally. The only requirement is that your model's properties invoke PropertyChanged.

For example, the demo in the RadDataForm Getting Started article is sufficient. The only thing you need is a reference to the object being used for the Source. In the case of that example, since the XAML doesn't have an x:Name for the SourceItem, you would just do this to change a value:

(dataForm.Source as SourceItem).Name = "New Name";

To make the example simpler so we can focus on the relevant part, I've written a new demo. 

Demo

You can find the runnable project attached, click the button to increase the inventory value represented by the InStock property. You will see that while updating the InStock property, the DataForm shows those changes in real time.

For your convenience, here is the relevant code:

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:input="clr-namespace:Telerik.XamarinForms.Input;assembly=Telerik.XamarinForms.Input"
             mc:Ignorable="d"
             x:Class="TwoWayBindingTest.MainPage">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <input:RadDataForm x:Name="DataForm"/>

        <Button Text="Increase Inventory"
                Clicked="Button_OnClicked"
                Margin="10"
                Grid.Row="1"/>
    </Grid>

</ContentPage>

MainPage.xaml.cs

using System.ComponentModel;
using Telerik.XamarinForms.Input;
using Xamarin.Forms;

namespace TwoWayBindingTest
{
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        private Book currentBook;

        public MainPage()
        {
            InitializeComponent();

            currentBook = new Book
            {
                Title = "The Martian",
                Price = 19.99,
                InStock = 43
            };

            DataForm.Source = currentBook;

            DataForm.RegisterEditor(nameof(Book.Title), EditorType.TextEditor);
            DataForm.RegisterEditor(nameof(Book.Price), EditorType.DecimalEditor);
            DataForm.RegisterEditor(nameof(Book.InStock), EditorType.IntegerEditor);
        }

        private void Button_OnClicked(object sender, EventArgs e)
        {
            currentBook.InStock = currentBook.InStock + 1;
        }
    }
}

Book.cs

using Telerik.XamarinForms.Common;
using Telerik.XamarinForms.Common.DataAnnotations;

namespace TwoWayBindingTest
{
    public class Book : NotifyPropertyChangedBase
    {
        private string title;
        private double price;
        private int inStock;

        [DisplayOptions(Header = "Title")]
        public string Title
        {
            get => title;
            set => UpdateValue(ref title, value);
        }

        [DisplayOptions(Header = "Price")]
        public double Price
        {
            get => price;
            set => UpdateValue(ref price, value);
        }

        [DisplayOptions(Header = "Inventory")]
        public int InStock
        {
            get => inStock;
            set => UpdateValue(ref inStock, value);
        }
    }
}

I hope this helps clarify how the DataForm identifies property changes.

Side Note

Since you mentioned that you may be updating values from the result of async calls, be sure that the code updates the property values on the UI thread. If the Task isn't returning to the same thread context, you will want to use Device.BeginInvoke to marshal the call back to the UI thread. This is the same as you'd do for any UI bound property.

For example, here's modified version of the demo with a simulated network call that doesn't return to the UI thread:

private async void Button_OnClicked(object sender, EventArgs e)
{
    await SomeApiCallAsync().ConfigureAwait(false);
}

private async Task SomeApiCallAsync()
{
    // Simulating some long running network based work
    await Task.Delay(250);

    // Because the task isn't returning result to UI thread, marshall this to the UI thread using BeginInvoke
    Device.BeginInvokeOnMainThread(() =>
    {
        currentBook.InStock = currentBook.InStock + 1;
    });
}

Regards, Lance | Technical Support Engineer, Principal
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
DataForm
Asked by
Sadanan
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Share this question
or