3

I'm asking myself if there's a better way to bind to a nested property.

The set up is: Custom control inside a custom view inside a custom page.

So: CustomControl -> CustomView -> CustomPage

The CustomControl has an entry and I ultimately want the TextProperty of this entry to be available for binding from CustomPage.

What I have now is a BindableProperty inside CustomControl which binds to a property inside CustomView which binds to a BindableProperty inside CustomView which binds to a property inside CustomPage which binds to a BindableProperty inside CustomPage.

So the flow is: BindableProperty(CustomControl) -> Property(CustomView) -> BindableProperty(CustomView) -> Property(CustomPage) -> BindableProperty(CustomPage)

Is this the correct way to do it? Sorry for the confusing text.

Some visualization: enter image description here

Update Lot of code inc.

Control, xaml:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:controls="removed"
         x:Class="removed"
         x:Name="this">
<ContentView.Content>
        <controls:Entry x:Name="entry" Text="{Binding EntryText, Source={x:Reference this}}"/>
</ContentView.Content>

Control, code behind:

public partial class HeaderSearchBarView : ContentView
{
    public event EventHandler CancelButtonClicked;

    public static readonly BindableProperty EntryTextProperty = BindableProperty.Create(
                                                     propertyName: nameof(EntryText),
                                                     returnType: typeof(string),
                                                     declaringType: typeof(HeaderSearchBarView),
                                                     defaultValue: null,
                                                     defaultBindingMode: BindingMode.TwoWay);

    public HeaderSearchBarView()
    {
        InitializeComponent();
    }

    public string EntryText
    {
        get => (string)GetValue(EntryTextProperty);
        set => SetValue(EntryTextProperty, value);
    }
}

View with control inside:

public partial class HeaderView : ContentView
{
    public static readonly BindableProperty SearchBarTextProperty = BindableProperty.Create(
                                                     propertyName: nameof(SearchBarText),
                                                     returnType: typeof(string),
                                                     declaringType: typeof(HeaderView),
                                                     defaultValue: null,
                                                     defaultBindingMode: BindingMode.TwoWay);

    private HeaderSearchBarView headerSearchBarView = new HeaderSearchBarView();

    public HeaderView()
    {
        InitializeComponent();
        Content = navigationDrawer;

        headerSearchBarView.SetBinding(HeaderSearchBarView.EntryTextProperty, new Binding(path: nameof(SearchBarText), source: this));
    }

    public string SearchBarText
    {
        get => (string)GetValue(SearchBarTextProperty);
        set => SetValue(SearchBarTextProperty, value);
    }
}

Page with view inside, xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:headerView="removed"
         x:Class="removed"
         x:Name="this">
<ContentPage.Content>
    <StackLayout>
        <headerView:HeaderView x:Name="headerView"
                               IsSearchBarButtonVisible="{Binding IsSearchBarButtonVisible, Source={x:Reference this}}"/>
    </StackLayout>
</ContentPage.Content>

Page with view inside, code behind:

public partial class BaseContentPage : ContentPage
{
    public static readonly BindableProperty SearchBarTextProperty = BindableProperty.Create(
                                                     propertyName: nameof(SearchBarText),
                                                     returnType: typeof(string),
                                                     declaringType: typeof(BaseContentPage),
                                                     defaultValue: null,
                                                     defaultBindingMode: BindingMode.TwoWay);

    public BaseContentPage() : base()
    {
        InitializeComponent();
    }

    public string SearchBarText
    {
        get => (string)GetValue(SearchBarTextProperty);
        set => SetValue(SearchBarTextProperty, value);
    }
}

With this i am able to bind to SearchBarText of BaseContentPage, which binds ultimately to TextProperty of the Entry in my Control:

<local:BaseContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                   xmlns:controls="removed"
                   x:Class="removed"
                   SearchBarText="{Binding SearchBarText}">

</local:BaseContentPage>

It works, but it seems overly complicated. Maybe there is a better way?

Remo
  • 65
  • 5
  • At first glance it seems unnecessary, but without seeing the XAML and VM I can't be sure. My initial thought is to give the page a name like "x:name="this"" and then you can bind to the pages binding context from the text box. See my [answer here](https://stackoverflow.com/a/62827364/8395242) on a similar question – Andrew Feb 02 '22 at 16:55
  • Thanks for your answer, but i think that doesn't work. – Remo Feb 02 '22 at 18:40
  • It need to pass the value level by level. On my test, each level needs a property. – Wendy Zang - MSFT Feb 18 '22 at 07:37

0 Answers0