Search code examples
xamlxamarinxamarin.formsdata-bindingxamarin-binding

Can't create Bindable Property for custom ContentView


I have created a ContentView with a single Label (I plan to add more later).

PageHeadingView.xaml

  <ContentView.Content>
        <StackLayout Orientation="Vertical" BackgroundColor="Red">
            <Label x:Name="HeadingLabel"  Text="{Binding HeadingText}" />
        </StackLayout>
  </ContentView.Content>

I defined a BindableProperty in my code behind. I also set the BindingContext of my view to be itself.

PageHeadingView.xaml.cs

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PageHeadingView : ContentView
{
    public PageHeadingView()
    {
        InitializeComponent();
        this.BindingContext = this;
    }

    public static readonly BindableProperty HeadingTextProperty = BindableProperty.Create(nameof(HeadingText), typeof(string), typeof(PageHeadingView), default(string));
    public string HeadingText { get => (string)GetValue( HeadingTextProperty); set => SetValue(HeadingTextProperty, value); }
}

I then added the View to my ContentPage. I also added a test Label inside a StackLayout to ensure my bindings were working correctly.

HomePage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:MyProject.Views"
             x:Class="MyProject.HomePage">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical">
            <views:PageHeadingView HeadingText="{Binding Name}" />
            <Label Text="{Binding Name}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

And set my BindingContext in code.

HomePage.xaml.cs

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
    public HomePage()
    {
        InitializeComponent();
        //ViewModel contains a string property named: Name;
        this.BindingContext = new ViewModel();
    }
}

When I run my code, my PageHeadingView does not display any text. I can see the red background color, so I know the control has been added to the Page correctly. The test Label I placed in StackLayout also works correctly, and I am able to see the bound value.

What do I need to do to make my CustomView display Bindable content?


Solution

  • From your code, you may have some problems when using bindableproperty bidning, I create simple sample that you can take a look:

    PageHeadingView.xaml:

     <ContentView.Content>
        <StackLayout BackgroundColor="Red" Orientation="Vertical">
            <Label x:Name="HeadingLabel" />
        </StackLayout>
    </ContentView.Content>
    

    PageHeadingView.cs, you can update HeadingText value by HeadingTextPropertyChanged, then display HeadingLabel.

     public partial class PageHeadingView : ContentView
    {
    
        public static BindableProperty HeadingTextProperty= BindableProperty.Create(
                                                         propertyName: "HeadingText",
                                                         returnType: typeof(string),
                                                         declaringType: typeof(PageHeadingView),
                                                         defaultValue: "",
                                                         defaultBindingMode: BindingMode.OneWay,
                                                         propertyChanged: HeadingTextPropertyChanged);
        
        public string HeadingText
        {
            get { return base.GetValue(HeadingTextProperty).ToString(); }
            set { base.SetValue(HeadingTextProperty, value); }
        }
        private static void HeadingTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (PageHeadingView)bindable;
            control.HeadingLabel.Text = newValue.ToString();
        }
    
        public PageHeadingView()
        {
            InitializeComponent();
        }
    }
    
    <StackLayout>
            <customcontrol:PageHeadingView HeadingText="{Binding Name}" />
            <Label Text="{Binding Name}" />
        </StackLayout>