Symxn
Symxn

Reputation: 65

Bindable property of custom control not updating - Xamarin Forms

I have created a custom control that contains a label that binds its text to a bindable property.

XAML of custom control:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestProject.CustomControls.MessageBar"
             HorizontalOptions="Fill"
             VerticalOptions="End"
             x:Name="this">
    <Frame BackgroundColor="{StaticResource MessageBarColor}"
           CornerRadius="0"
           Padding="0">
        <Label Text="{Binding MessageText, Source={x:Reference this}, Mode=OneWay}"
               LineBreakMode="TailTruncation"
               MaxLines="3"
               FontSize="13"
               TextColor="White"
               HorizontalOptions="Start"
               VerticalOptions="Center"
               Margin="20,16"></Label>
    </Frame>
</ContentView>

Code behind of custom control:

using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace TestProject.CustomControls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MessageBar : ContentView
    {
        public static readonly BindableProperty MessageTextProperty = BindableProperty.Create(
            propertyName: nameof(MessageText),
            returnType: typeof(string),
            declaringType: typeof(MessageBar),
            defaultValue: default(string));

        public string MessageText
        {
            get { return (string)GetValue(MessageTextProperty); }
            set { SetValue(MessageTextProperty, value); }
        }

        public MessageBar()
        {
            InitializeComponent();
        }
    }
}

Now my problem: If I use the control in a page and set the MessageText property in XAML, everything works fine. The text is displayed. But when I bind the MessageText property to a ViewModel, no text is displayed. The MessageText property is not set at all.

XAML of page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:customControls="clr-namespace:TestProject.CustomControls"
             x:Class="TestProject.MVVM.Pages.ExamplePage">
    <StackLayout Orientation="Vertical">

        <!-- Works fine -->
        <customControls:MessageBar MessageText="This is a message!"></customControls:MessageBar>

        <!-- It does not work -->
        <customControls:MessageBar MessageText="{Binding Message, Mode=OneWay}"></customControls:MessageBar>
    </StackLayout>
</ContentPage>

ViewModel of page:

using Prism.Mvvm;

namespace TestProject.MVVM.ViewModels
{
    public class ExampleViewModel : BindableBase
    {
        private string _message;

        public string Message
        {
            get { return _message; }
            set { SetProperty(ref _message, value); }
        }

        public ExampleViewModel()
        {
            Message = "Message from viewModel!";
        }
    }
}

What am I doing wrong?

P.S.:

I have already found some posts on this topic, but they did not contain any working solutions. Many suggested giving the custom control a name and binding the property with x:Reference. I did this as you can see, but it still doesn't work.

Upvotes: 0

Views: 2927

Answers (2)

Jasmin Sojitra
Jasmin Sojitra

Reputation: 1301

Hello, Have you register ViewModel with the view in App.cs file Like this

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
}

Upvotes: 0

nevermore
nevermore

Reputation: 15786

There is nothing wrong with your Custom control, I use a simple model and it works well on my side. Check the BindingContext and message in your ExamplePage.cs.

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        ExampleViewModel vm = new ExampleViewModel();
        vm.Message = "test";
        BindingContext = vm;
    }
}

public class ExampleViewModel : INotifyPropertyChanged
{
    private string _message;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Message
    {
        set
        {
            if (_message != value)
            {
                _message = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Message"));
                }
            }
        }
        get
        {
            return _message;
        }
    }

    public ExampleViewModel()
    {
        Message = "Message from viewModel!";
    }
}

I uploaded a sample project here.

Upvotes: 1

Related Questions