Robert
Robert

Reputation: 105

Xamarin Forms ContentView Binding Issue

Description

Xamarin Forms does not bind to ContentView properties as expected.

Goal

Reuse visual elements whenever possible to maintain consistent style and decrease duplicate code.

Expected

BindableProperty in the ContentView should be set with MyText="{Binding Text}" and be rendered as shown here:

Actual

The BindableProperty is not set as expected and is rendered as shown here:

Environment

Code

Solution code has been uploaded to GitHub.

ItemsPage.xaml

<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Items}" SelectionMode="None">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="model:Item">
            <Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto" BackgroundColor="LightGray">
                <!-- ItemsPage Binding -->
                <Label Grid.Column="0" Text="{Binding Text}" BackgroundColor="DarkGray" />

                <!-- ContentView Static Text-->
                <cv:MyContentView Grid.Column="1" MyText="Text!" />

                <!-- ContentView Binding -->
                <cv:MyContentView Grid.Column="2" MyText="{Binding Text}" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

MyContentView.xaml

<Label Text="{Binding MyText}" BackgroundColor="DarkBlue" TextColor="White" />

MyContentView.xaml.cs

public static readonly BindableProperty MyTextProperty =
    BindableProperty.Create(nameof(MyText), typeof(string), typeof(MyContentView),
    default(string), propertyChanged: MyTextChanged);
private static void MyTextChanged(BindableObject bindable, object oldValue, object newValue)
{
    // Called 7 times on first load (there are only 5 items in the MockDataStore).
    // Called 1 time when performing a RefreshView/LoadItemsCommand.
    Debug.WriteLine($"MyTextChanged, oldValue: {oldValue}, newValue: {newValue}");
    ((MyContentView)bindable).MyTextChanged((string)oldValue, (string)newValue);
}
private void MyTextChanged(string oldValue, string newValue)
{
    MyText = newValue;
}
public string MyText
{
    get
    {
        return (string)GetValue(MyTextProperty);
    }
    private set
    {
        SetValue(MyTextProperty, value);
    }
}

Application Output

MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!
MyTextChanged, oldValue: , newValue: Text!

Upvotes: 1

Views: 452

Answers (1)

Shubham Tyagi
Shubham Tyagi

Reputation: 837

Remove binding context in constructor

public MyContentView()
{
   InitializeComponent();
   //BindingContext = this;
}

Add Source to your binding

<ContentView
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="BindingIssue.ContentViews.MyContentView"
    x:Name="myContentView">
    <ContentView.Content>
        <Label Text="{Binding MyText,Source={x:Reference myContentView}}" BackgroundColor="DarkBlue" TextColor="White"/>
    </ContentView.Content>
</ContentView>

Voila!

Upvotes: 2

Related Questions