Can't create Bindable Property for custom ContentView

210 Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER

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>
3
On

You are binding the wrong element in PageHeadingView.

Option 1:
Add "Content" in PageHeadingView.xaml.cs

this.Content.BindingContext = this;

Option 2:
Remove "Content" in PageHeadingView.xaml

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

Edited as quoted the wrong class previously.