Currently I am playing around with .Net Maui but I maybe it's the same behavior as Xamarin.
I've created a simple Search-Control which is based on a ContentView
.
ObjectSearchControl.xaml
<ContentView
x:Class="DeepBlue.Controls.ObjectSearchControl"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converter="clr-namespace:DeepBlue.Converter"
xmlns:selector="clr-namespace:DeepBlue.Helpers"
x:Name="MySearchControl">
<StackLayout
Orientation="Vertical"
VerticalOptions="FillAndExpand">
<SearchBar
x:Name="ObjectSearchBar"
IsSpellCheckEnabled="False"
Keyboard="Text"
Placeholder="{Binding SearchBarPlaceholderText}"
TextChanged="ObjectSearchBar_TextChanged" />
<CollectionView
x:Name="ObjectResultView"
HeightRequest="500"
ItemsSource="{Binding DataSource}"
SelectionChanged="ObjectResultView_SelectionChanged">
</CollectionView>
</StackLayout>
</ContentView>
ObjectSearchControl.xaml.cs
public partial class ObjectSearchControl : ContentView
{
public static readonly BindableProperty SearchBarPlaceholderTextProperty
= BindableProperty.Create(nameof(SearchBarPlaceholderText), typeof(string),
typeof(ObjectSearchControl), string.Empty);
public static readonly BindableProperty DataSourceProperty
= BindableProperty.Create(nameof(DataSource), typeof(object),
typeof(ObjectSearchControl));
public ObjectSearchControl()
{
InitializeComponent();
Content.BindingContext = this;
}
public string SearchBarPlaceholderText
{
get => (string)GetValue(SearchBarPlaceholderTextProperty);
set => SetValue(SearchBarPlaceholderTextProperty, value);
}
public object DataSource
{
get => (object)GetValue(DataSourceProperty);
set => SetValue(DataSourceProperty, value);
}
}
This ContentView
I've inserted in my Page
<StackLayout
x:Name="SelectFishingSection"
HeightRequest="600"
HorizontalOptions="FillAndExpand"
Orientation="Vertical"
VerticalOptions="FillAndExpand">
<controls:ObjectSearchControl
DataSource="{Binding NonFilterdDataSource}"
HeightRequest="550"
HorizontalOptions="FillAndExpand"
SearchBarPlaceholderText="Placeholder"
VerticalOptions="FillAndExpand" />
</StackLayout>
After running the code the control rendered and the Placeholdertext in the SearchBar
is set correct. So I thought the implementation of the binding is correct. But in my CollectionView
no element is rendered.
So I debugged a lot and found out that the BindingContext
is set 2 times. When I initialize the control all the properties have got NULL values. -> seems okay
Then the control is appearing and I get the elements from DB and set them to "DataSource".
<ContentPage.Behaviors>
<mctBehaviors:EventToCommandBehavior Command="{Binding SetDataSourcesCommand}" EventName="Appearing" />
</ContentPage.Behaviors>
private async Task SetDataSources()
{
try
{
IsBusy = true;
NonFilterdDataSource = new ObservableCollection<MyTestModel>(await DataService.GetAll());
}
finally
{
IsBusy = false;
}
}
That's also called and seems correct. After that BindingContext
is set (OnBindingContextChanged
is called in my ObjectSearchControl.xaml.cs) and all properties (SearchBarPlaceholderText and DataSource) have got correct values. At this point in DataSource there are 9 Elements!
If I continue debugging the DataSource is set to NULL and also the BindingContext
is set to NULL! But I don't understand why?
Output window in VS shows only "External Code" and I can not figure out why this is happening.
I found a few similar questions but none of the could solve my problem.
After analysing the "External Code" in VS I found out that the source of the problem must be somewhere in the measurement for the control. So I removed
VerticalOptions="FillAndExpand"
from mycontrols:ObjectSearchControl
implemention and after that the problem was gone. BindingContext is set only one time and everything is working as expected!