Open Tommigun1980 opened 3 years ago
Workaround found!
Bindings for a custom view inside a CarouselView will work if, instead of doing the following in the custom view:
<ContentView
...
x:Name="myRoot"
BindingContext="{x:Reference myRoot}">
...
<Label Text="{Binding SomeBinding} />
... every binding specifies a binding source instead:
<Label Text="{Binding SomeBinding, Source={x:Reference myRoot}} />
This is is only needed if the custom view resides inside a CarouselView (and possibly a CollectionView - didn't test). Doing this also clutters the XAML a lot, where a one-time assignment is much cleaner and works everywhere else.
Very much related issue: https://github.com/xamarin/Xamarin.Forms/issues/13664
I think this is not a bug but how Binding and it's Source (BindingContext) works. A way to fix this could be:
On your MyView change the Bindable Property to something like:
public static readonly BindableProperty MyNameProperty = BindableProperty.Create(
nameof(MyName), typeof(string), typeof(MyView),
propertyChanged: (BindableObject bindable, object oldValue, object newValue) => (bindable as MyView).lbl.Text = newValue?.ToString(););
Remove the BindingContext from the xaml on MyView, and add a x:name to the label
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CarouselViewContentsLoseBindings.Views.MyView"
x:Name="myViewRoot">
<ContentView.Content>
<Frame BorderColor="Blue">
<StackLayout>
<Label
Text="My View"
HorizontalTextAlignment="Center" />
<Label x:Name="lbl"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</StackLayout>
</Frame>
</ContentView.Content>
</ContentView>
and then use it like
<views:MyView MyName="{Binding ., Mode=OneTime, StringFormat='Binding: \'{0}\''}" />
I think this is not a bug but how Binding and it's Source (BindingContext) works. A way to fix this could be:
On your MyView change the Bindable Property to something like:
public static readonly BindableProperty MyNameProperty = BindableProperty.Create( nameof(MyName), typeof(string), typeof(MyView), propertyChanged: (BindableObject bindable, object oldValue, object newValue) => (bindable as MyView).lbl.Text = newValue?.ToString(););
Remove the BindingContext from the xaml on MyView, and add a x:name to the label
<?xml version="1.0" encoding="UTF-8" ?> <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="CarouselViewContentsLoseBindings.Views.MyView" x:Name="myViewRoot"> <ContentView.Content> <Frame BorderColor="Blue"> <StackLayout> <Label Text="My View" HorizontalTextAlignment="Center" /> <Label x:Name="lbl" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" /> </StackLayout> </Frame> </ContentView.Content> </ContentView>
and then use it like
<views:MyView MyName="{Binding ., Mode=OneTime, StringFormat='Binding: \'{0}\''}" />
Thank you. But why would it matter where the control is used? The "normal" way works as long as the control is not inside a CarouselView, which is populated from an ObservableCollection.
Having to hard-code it like that forces the control to "know" where it’s going to be used, and removes the usefulness of bindings.
The difference is that on a DataTemplate the BindingContext of that view is replaced by the context of the item on the collection.
Description
Bindings for a custom view inside a CarouselView don't work properly:
The screenshot contains of a CarouselView with a data template consisting of the following: 1) A label, where its text is bound to the current item in the ItemsSource ("Item 1"). This works. 2) A custom view (blue border), where its binding is fed with a hard-coded value. This works. 3) A custom view (blue border), where its binding is fed with the current item in the ItemsSource ("Item 1"). This doesn't work and the binding comes out as blank.
This is problematic as the CarouselView is not able to use any components/visualizations I have created, ones I am using everywhere else.
So to reiterate, the following does not work inside a CarouselView:
(where 'Binding .' is the CarouselView's ItemsSource instance)
While this does work inside a CarouselView:
Tested only on iOS, don't know if it also happens on Android. There are some issues that sound quite similar, such as https://github.com/xamarin/Xamarin.Forms/issues/13376.
Steps to Reproduce
1) Run the attached repro project. 2) Inspect the ItemsSource bindings not working for custom views inside the CarouselView.
Expected Behavior
Custom views with bindings should work inside CarouselViews.
Actual Behavior
Custom views with bindings don't work inside CarouselViews.
Basic Information
Environment
Show/Hide Visual Studio info
``` === Visual Studio Community 2019 for Mac (Preview) === Version 8.9 Preview (8.9 build 1451) Installation UUID: 72636114-810a-4854-b886-e8b8d8efe7d3 GTK+ 2.24.23 (Raleigh theme) Xamarin.Mac 6.18.0.23 (d16-6 / 088c73638) Package version: 612000113 === Mono Framework MDK === Runtime: Mono 6.12.0.113 (2020-02/4fdfb5b1fd5) (64-bit) Package version: 612000113 === Xamarin Designer === Version: 16.9.0.266 Hash: c4842c761 Branch: remotes/origin/c4842c761b9b6a95407f72278ca7fb42f8f7fdf0 Build date: 2021-01-07 06:17:08 UTC === Roslyn (Language Service) === 3.9.0-3.20619.14+df59a33fd9beff9790e01a2a1ab21e4a1e6921b3 === NuGet === Version: 5.8.0.6860 === .NET Core SDK === SDK: /usr/local/share/dotnet/sdk/5.0.102/Sdks SDK Versions: 5.0.102 5.0.101 5.0.100 3.1.405 3.1.404 3.1.403 MSBuild SDKs: /Applications/Visual Studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/Sdks === .NET Core Runtime === Runtime: /usr/local/share/dotnet/dotnet Runtime Versions: 5.0.2 5.0.1 5.0.0 3.1.11 3.1.10 3.1.9 === .NET Core 3.1 SDK === SDK: 3.1.405 === Xamarin.Profiler === Version: 1.6.15.68 Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler === Updater === Version: 11 === Apple Developer Tools === Xcode 12.4 (17801) Build 12D4e === Xamarin.Mac === Xamarin.Mac not installed. Can't find /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/Version. === Xamarin.iOS === Version: 14.9.0.27 (Visual Studio Community) Hash: f4c9327fa Branch: main Build date: 2020-11-19 10:57:31-0500 === Xamarin.Android === Version: 11.2.0.0 (Visual Studio Community) Commit: xamarin-android/d16-9/f908d16 Android SDK: /Users/tommikiviniemi/Library/Developer/Xamarin/android-sdk-macosx Supported Android versions: None installed SDK Tools Version: 26.1.1 SDK Platform Tools Version: 30.0.4 SDK Build Tools Version: 30.0.2 Build Information: Mono: 5e9cb6d Java.Interop: xamarin/java.interop/d16-9@1d382be ProGuard: Guardsquare/proguard/v7.0.1@912d149 SQLite: xamarin/sqlite/3.32.2@cfe06e0 Xamarin.Android Tools: xamarin/xamarin-android-tools/main@ad80a42 === Microsoft OpenJDK for Mobile === Java SDK: /Users/tommikiviniemi/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.25 1.8.0-25 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL === Android SDK Manager === Version: 16.9.0.21 Hash: 57e40ba Branch: remotes/origin/main Build date: 2021-01-08 01:57:14 UTC === Android Device Manager === Version: 16.9.0.14 Hash: 0fdccda Branch: remotes/origin/main Build date: 2021-01-08 01:57:36 UTC === Build Information === Release ID: 809001451 Git revision: cfd15313a6388ef8dada0182e22a058131c46f9d Build date: 2021-01-15 08:42:21-05 Build branch: release-8.9 Xamarin extensions: cfd15313a6388ef8dada0182e22a058131c46f9d === Operating System === Mac OS X 10.16.0 Darwin 20.3.0 Darwin Kernel Version 20.3.0 Thu Jan 21 00:07:06 PST 2021 root:xnu-7195.81.3~1/RELEASE_X86_64 x86_64 ```Screenshots
Reproduction Link
CarouselViewContentsLoseBindings.zip
Workaround
See first follow-up comment for a workaround.