0

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?

Dave
  • 3,676
  • 4
  • 28
  • 39

2 Answers2

1

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.

Shaw
  • 907
  • 1
  • 8
  • 20
  • Option #2 didn't seem to work for me. I tried every combination of removing the Content element from the Page and the ContentView, but my text still didn't didn't show up. Option #1, however, did work. So thank you! – Dave Jan 28 '21 at 13:34
  • Upon further investigation, I noticed that Option #1 only works with bound values. If I use a constant in my ContentPage, the value does not display. For this reason, I have marked Cherry's answer as correct, as it handles all situations. – Dave Jan 28 '21 at 15:58
  • Oops, I mentioned "binding the wrong element in PageHeadingView" but quoted the "HomePage" class afterwards, sorry about my carelessness. Edited and that should work as same as using a PropertyChanged method. – Shaw Jan 28 '21 at 19:58
1

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>
Cherry Bu - MSFT
  • 10,160
  • 1
  • 10
  • 16