Creating a custom data binding in MvvmCross involves defining how to bind a specific property of a view to a property in a view model. This is particularly useful when MvvmCross does not support the binding out of the box, such as in two-way mode or when dealing with custom views that require additional parameters. Hereâs a step-by-step guide on how to create a custom data binding:
Understanding the Basics
- Target: The property on your view that you want to bind.
- Source: The property in your view model that you want to bind to.
- Target Binding: A class that defines how to bind a view property to a view model property.
Creating a Custom Target Binding
To create a custom target binding, you need to write a class that inherits from `MvxTargetBinding`. Hereâs an example of how to bind a custom view's property called `MyProperty`:
csharp
public class MyViewMyPropertyTargetBinding : MvxPropertyInfoTargetBinding
{
private bool _subscribed;
public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay;
public MyViewMyPropertyTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
// This constructor is used to initialize the binding.
}
protected override void SetValueImpl(object target, object value)
{
var view = target as MyView;
if (view == null) return;
view.MyProperty = (string)value;
}
public override void SubscribeToEvents()
{
var myView = View;
if (myView == null)
{
MvxBindingTrace.Trace(MvxTraceLevel.Error, "Error - MyView is null in MyViewMyPropertyTargetBinding");
return;
}
_subscribed = true;
myView.MyPropertyChanged += HandleMyPropertyChanged;
}
private void HandleMyPropertyChanged(object sender, EventArgs e)
{
var myView = View;
if (myView == null) return;
FireValueChanged(myView.MyProperty);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var myView = View;
if (myView != null && _subscribed)
{
myView.MyPropertyChanged -= HandleMyPropertyChanged;
_subscribed = false;
}
}
}
}
Registering the Custom Target Binding
After defining the custom target binding, you need to register it in your `Setup.cs` file by overriding the `FillTargetFactories` method:
csharp
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterPropertyInfoBindingFactory(
typeof(MyViewMyPropertyTargetBinding),
typeof(MyView), "MyProperty");
}
Using the Custom Binding
Once the custom binding is registered, you can use it in your views like any other binding:
csharp
var aView = new MyView();
set.Bind(aView).For("MyProperty").To(vm => vm.value);
If you want to avoid specifying the property name every time you bind, you can set a default binding name in your `Setup.cs` file.
Additional Considerations
- MvxConvertingTargetBinding: This class is useful for preventing feedback loops when using converters.
- MvxPropertyInfoTargetBinding: A subclass of `MvxConvertingTargetBinding`, it simplifies creating one-way bindings by automatically implementing the `SetValue` method based on `PropertyInfo`.
- MvxWithEventPropertyInfoTargetBinding: A shortcut for creating two-way bindings based on a specific event.
Creating custom bindings allows you to extend MvvmCross's capabilities to handle any custom view or property you might need in your application.
Citations:[1] https://www.mvvmcross.com/documentation/advanced/custom-data-binding
[2] https://stackoverflow.com/questions/28798209/mvvmcross-binding-your-datamodel-to-your-viewmodel
[3] https://learn.microsoft.com/en-us/archive/msdn-magazine/2014/august/windows-phone-build-mvvm-apps-with-xamarin-and-mvvmcross
[4] https://blog.ostebaronen.dk/2018/01/mvvmcross-binding-target.html
[5] https://www.mvvmcross.com/documentation/getting-started/getting-started
[6] https://stackoverflow.com/questions/10700445/in-mvvmcross-how-do-i-do-custom-bind-properties
[7] https://www.mvvmcross.com/documentation/fundamentals/data-binding
[8] https://crosscuttingconcerns.com/MvvmCross-Fluent-Databinding