Access a custom controls bindable properties from its xaml

325 Views Asked by At

I want to declare a bindable property in my custom view and link it to the corresponding viewmodel.

I use the MVVM pattern and want to separate ui logic and data logic from eachother. So I keep my status and other data in the viewmodel and update my view according to viewmodel data changes.

This of course should be done by data binding.

Lets say I got the following xaml ...

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:MyApp.Views.Controls"
             x:Class="MyApp.Views.Controls.MyView"
             x:DataType="controls:MyViewVm">
    <!--TODO: Content-->
</ContentView>

... with this code behind ...

using System.Runtime.CompilerServices;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace MyApp.Views.Controls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MyView : ContentView
    {
        public static readonly BindableProperty StatusProperty = BindableProperty.Create(nameof(Status), typeof(MyStatus), typeof(MyView));

        public MyStatus Status
        {
            get => (MyStatus)GetValue(StatusProperty);
            set => SetValue(StatusProperty, value);
        }

        public MyView()
        {
            InitializeComponent();
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);

            switch (propertyName)
            {
                case nameof(Status):
                    // TODO: Do styling ...
                    break;
            }
        }
    }
}

... and this viewmodel and status enum:

namespace AbrechnungsApp.Views.Controls
{
    public class MyViewVm : ViewModelBase
    {
        public MyStatus Status { get; set; }
    }

    public enum MyStatus
    {
        Enabled,
        Disabled,
        Readonly
    }
}

Now the question is:

How do I link my viewmodels Status property to my views Status bindable property?

1

There are 1 best solutions below

0
On

I typically create a helper property to cast BindingContext to the appropriate VM class:

private MyViewVm VM => (MyViewVm)BindingContext;

Then get/set VM properties in the bindable property:

public static readonly BindableProperty StatusProperty =
    BindableProperty.Create(
        nameof(Status), typeof(MyStatus), typeof(MyView),
        propertyChanged: (binding, old, new) =>
            {
                // Needed if your XAML uses two-way binding.
                Status = new;
            });

    public MyStatus Status
    {
        get => VM.Status;
        set => VM.Status = value;
    }