Reputation: 3153
How can I Pass a Binding from a Page
to a View
?
I have this Page(Xaml)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:DataBindingTests.Views"
xmlns:model="clr-namespace:DataBindingTests.ViewModels"
x:Class="DataBindingTests.Pages.CoolePage"
Title="CoolePage"
x:DataType="model:CoolesModel">
<VerticalStackLayout>
<Label Text="{Binding YourName}"></Label>
<views:MainView YourName="{Binding YourName}"></views:MainView>
<Button Command="{Binding ChangeNameCommand}"></Button>
</VerticalStackLayout>
</ContentPage>
And its CodeBehind:
using DataBindingTests.ViewModels;
namespace DataBindingTests.Pages;
public partial class CoolePage : ContentPage
{
public CoolePage()
{
this.BindingContext = new CoolesModel();
InitializeComponent();
}
}
If I pass a String into my MainView it works and all events are fired. When I use the binding it doesn't. In this simple test, the app should display two times the same name, but only the Label of the ContentPage has the YourName
property printed
<views:MainView YourName="Lars"></views:MainView> <-- Works
<views:MainView YourName="{Binding YourName}"></views:MainView> <-- doesn't work
This is the Xaml of the MainView
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:DataBindingTests.Views"
x:Class="DataBindingTests.Views.MainView">
<VerticalStackLayout>
<Label Text="{Binding YourName}"
VerticalOptions="Center"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentView>
This is the CodeBehind of the MainView
namespace DataBindingTests.Views;
public partial class MainView : ContentView
{
public String YourName
{
get
{
String value = (String)GetValue(MainView.YourNameProperty);
return value;
}
set
{
SetValue(MainView.YourNameProperty, value);
}
}
public static readonly BindableProperty YourNameProperty = BindableProperty.Create(nameof(YourName)
, typeof(String)
, typeof(MainView), defaultBindingMode:BindingMode.TwoWay, propertyChanged: OnYourNameChanged);
static void OnYourNameChanged(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine(newValue);
}
public MainView()
{
this.BindingContext = this; // Ignore ParentContext
InitializeComponent();
}
}
Upvotes: 0
Views: 2499
Reputation: 13889
You can just remove code this.BindingContext = this;
from the constructor of MainView.xaml.cs
:
public MainView()
{
//this.BindingContext = this;
InitializeComponent();
}
Update:
the above code would only work because the Property in the View and the Page have the same name.
In this condition, you can modify the code of MainView.xaml
as follows:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp929.MainView"
x:Name="TestControlView"
>
<VerticalStackLayout>
<Label Text="{Binding Source={x:Reference TestControlView}, Path=YourName}"
VerticalOptions="Center"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentView>
MainView.xaml.cs
public partial class MainView : ContentView
{
public String YourName
{
get
{
String value = (String)GetValue(YourNameProperty);
return value;
}
set
{
SetValue(YourNameProperty, value);
}
}
public static readonly BindableProperty YourNameProperty = BindableProperty.Create(nameof(YourName)
, typeof(String)
, typeof(MainView), defaultBindingMode: BindingMode.TwoWay, propertyChanged: OnYourNameChanged);
static void OnYourNameChanged(BindableObject bindable, object oldValue, object newValue)
{
Console.WriteLine("-----------------> "+newValue);
}
public MainView()
{
InitializeComponent();
// this.BindingContext = this;
}
}
CoolesModel.cs
public class CoolesModel
{
// public string YourName { get; set; }
public string Name { get; set; }
public string TestName { get; set; }
public ICommand ChangeNameCommand => new Command(changeMethod);
private void changeMethod()
{
}
public CoolesModel() {
//YourName = "abc";
Name = "abc";
TestName = "test123...";
}
}
MainPage.xaml.cs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mauiapp929="clr-namespace:MauiApp929"
x:Class="MauiApp929.MainPage">
<ScrollView>
<VerticalStackLayout>
<Label Text="{Binding Name}"></Label>
<mauiapp929:MainView YourName="{Binding TestName}"></mauiapp929:MainView>
<Button Command="{Binding ChangeNameCommand}"></Button>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Upvotes: 1
Reputation: 67447
In this simple test, the app should display two times the same name, but only the Label of the ContentPage has the YourName property printed
You're overwriting your binding context half way through for some reason, and the context your page binding resolves (the normal way of using it, the parent context) is different than what you actually see on the screen (which is your this.BindingContext = this
). And you never set your second context's property.
Upvotes: 0