question

ibocon avatar image
0 Votes"
ibocon asked ibocon edited

How to use compiled bindings with BindingContext in Xamarin XAML

I want to use x:DataType with BindingContext like below.

xaml
<ContentPage
    x:DataType="local:MainPageViewModel">
    <ContentPage.BindingContext>
        <local:MainPageViewModel />
    </ContentPage.BindingContext>

    <Label
        x:DataType="local:TitleViewModel"
        BindingContext ="{Binding InnerViewModel}" 
        Text="{Binding Title}" />

</ContentPage>


cs
public class MainPageViewModel
{
    private TitleViewModel _innerViewModel;
    public TitleViewModel InnerViewModel
    {
        get => _innerViewModel;
        set => SetProperty(ref _innerViewModel, value);
    }
}

public class TitleViewModel
{
    private string _title;
    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }
}




The reason why I am not using InnerViewModel.Title for binding is PropertyChanged event only checks property path. So, If I update InnerViewModel.Title, it raise PropertyChanged event with path "Title", not "InnerViewModel.Title". It cause a problem.

I know I can do like below to solve,

public class MainPageViewModel
{
    private void OnInnerViewModelPropertyChanged(object sender, PropertyChangedArgs e)
    {
        // ...
        RaisePropertyChanged(this, "InnerViewModel.Title");
    }
}

But, I prefer to change BindingContext instead relaying PropertyChanged event.



However, it builds fail because of below reason.

Error XFC0045: Binding: Property "InnerViewModel" not found on "Local.TitleViewModel".

Even if I delete x:DataType like below, still fail because MainPageViewModel does not have Title property.

xaml
<Label
    BindingContext ="{Binding InnerViewModel}"
    Text="{Binding Title}" />


Therefore, I give up to compiled bindings by using x:null like below.

xaml
<Label
    x:DataType="x:null"
    BindingContext ="{Binding InnerViewModel}" 
    Text="{Binding Title}" />
dotnet-xamarin
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

JarvanZhang-MSFT avatar image
0 Votes"
JarvanZhang-MSFT answered ibocon edited

Hello,​

Welcome to our Microsoft Q&A platform!

It's recommended to set the x:DataType attribute at the same level in the view hierarchy as the BindingContext is set. However, this attribute can be re-defined at any location in a view hierarchy. In your page, the label is not at the same level with the contentPage. So please re-define the BindingContext and x:DataType for the label.

Check the code:

<ContentPage ...
    x:DataType="local:TestPageViewModel">

    <StackLayout BindingContext="{Binding InnerViewModel}">
        <Label x:DataType="local:TitleViewModel" Text="{Binding Title}"/>
    </StackLayout>
</ContentPage>

To achieve the data binding, you could just specify the BindingContext for the view without using x:DataType.

<ContentPage ...><!--remove the x:DataType for the contentPage-->
    <ContentPage.BindingContext>
        <local:MainPageViewModel />
    </ContentPage.BindingContext>
    <StackLayout >
        <Label BindingContext="{Binding InnerViewModel}" Text="{Binding Title}"/>
    </StackLayout>
</ContentPage>


Best Regards,

Jarvan Zhang


If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello, @JarvanZhang-MSFT.

I have an further question.

On the second part of your answer, you suggest remove the x:DataType which means cannot use compiled bindings.
Is there a way to maintain compiled bindings with BindingContext in same level?

The reason why I am obsessed with it is to avoid typo while binding and to check type before build XAML.

P.S
Thanks @JarvanZhang-MSFT. I know you answer a lot of questions and you did answer my questions before.
I wonder there is a plan to maintain or migrate valuable threads in 'Xamarin Community Forums'.
JamesMontemagno's announcement mentions nothing about it... and I can not ask about on the thread... Or should I send an email to JamesMontemagno?

0 Votes 0 ·

Is there a way to maintain compiled bindings with BindingContext in same level?

Please make sure the x:DataType and BindingContext are the same class type.

<StackLayout x:DataType="local:CustomViewModel">
    <StackLayout.BindingContext>
        <local:CustomViewModel />
    </StackLayout.BindingContext>
   
    <Label Text="{Binding Name}" />
</StackLayout>

I wonder there is a plan to maintain or migrate valuable threads in 'Xamarin Community Forums'.

Sorry, I don't see the related document about that. If you've some questions about Xamarin, please create new threads on Microsoft Q&A now.
0 Votes 0 ·

@ibocon May I know whether your issue has been solved or not? If not, please share it in here. We can work together to figure it out.

0 Votes 0 ·

@JarvanZhang-MSFT

I decided to maintain x:DataType="x:null" because I can not apply your suggestion.

My actual code shares CustomViewModel between views. Therefore, I can not create CustomViewModel every time view created as you suggest.

// first view
<StackLayout x:DataType="local:CustomViewModel">
    <StackLayout.BindingContext>
        <local:CustomViewModel />
   </StackLayout.BindingContext>

    <Label Text="{Binding Name}" />
</StackLayout>

// second view
<StackLayout x:DataType="local:CustomViewModel">
    // this should be equal object as first view's binding context.
    <StackLayout.BindingContext>
        <local:CustomViewModel />
   </StackLayout.BindingContext>

    <BoxView Color="{Binding Color}" />
</StackLayout>

0 Votes 0 ·