Reputation: 47
I've been learning the Xamarin framework lately, and I wanted to create a reusable control element that displays some properties of an object. To remove redundancy, I wanted to pass the complete object to the control and have it manage how to display it. However, I'm encountering strange behaviour when passing it an object from a binding.
Instead of receiving the object instance, it only receives some instance of Xamarin.Forms.internals<TypedBinding<CoffeeCounter.Demo.Page, CoffeeCounter.Demo.Parameter>. I'd either need to extract the instance of the object from this or change something such that the actual instance is already passed.
Here is a compact demo of the problem. First a simple page view, with an instance of the reusable control.
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:demo="clr-namespace:CoffeeCounter.Demo;assembly=CoffeeCounter"
x:Class="CoffeeCounter.Demo.Page"
x:DataType="demo:Page">
<ContentPage.Content>
<StackLayout>
<demo:Control Parameter="{Binding Parameter}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
It receives the parameter object with the properties to display from the code-behind.
using Xamarin.Forms;
namespace CoffeeCounter.Demo {
public partial class Page : ContentPage {
public Page() {
InitializeComponent();
}
public Parameter Parameter => new Parameter{Foo="Football", Bar="Barricade"};
}
}
And the parameter class simply looks like this.
namespace CoffeeCounter.Demo {
public class Parameter {
public string Foo {get; set;}
public string Bar {get; set;}
public override string ToString() {
return "Foo: " + Foo + ", " + "Bar: " + Bar;
}
}
}
The control is then built like this.
<?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="CoffeeCounter.Demo.Control">
<Label x:Name="Title" Text=""/>
</ContentView>
using Xamarin.Forms;
namespace CoffeeCounter.Demo {
public partial class Control {
public static readonly BindableProperty PARAMETER = BindableProperty.Create(
"Parameter",
typeof(object),
typeof(Control),
null,
BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) => {
var control = (Control) bindable;
control.Title.Text = newValue.ToString();
}
);
public object Parameter {
set => SetValue(PARAMETER, value);
}
public Control() {
InitializeComponent();
}
}
}
I'm aware the custom control can probably make use of bindings as well to update its contents, but that's not the point of this question.
Thanks in advance for any answers :)
Upvotes: 0
Views: 1367
Reputation: 439
Your code is correct but there are few errors.
public Page()
{
InitializeComponent();
BindingContext = this; //add this line
}
public Parameter Parameter => new Parameter { Foo = "Football", Bar = "Barricade" };
Your Control.Xaml.cs should be like this.
public Control()
{
InitializeComponent();
}
public static readonly BindableProperty ParameterProperty = BindableProperty.Create(
nameof(Parameter),
typeof(object),
typeof(Control),
null,
BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) => {
var control = (Control)bindable;
control.Title.Text = newValue.ToString();
}
);
public object Parameter
{
set => SetValue(ParameterProperty, value);
}
Upvotes: 1