Binding to two or more control properties using Caliburn (micro)
-
02-03-2021 - |
Question
The problem I'm trying to solve is fairly straight forward, I'm using Microsoft.Phone.Controls
and I'm trying to bind to two properties of ToggleSwitch
in my MainPageViewModel
so I can capture the state of the ToggleSwitch
and change its content from 'on/off' to 'distance/time' for example.
What I'm doing doesn't work, it's something to do with conventions that I haven't quite figured out from the docs (RTFM...). This doesn't work:
using System;
using System.Windows.Data;
using System.Collections.Generic;
using Caliburn.Micro;
using Microsoft.Phone.Controls;
public class AppBootstrapper : PhoneBootstrapper
{
PhoneContainer container;
protected override void Configure()
{
container = new PhoneContainer(RootFrame);
container.RegisterPhoneServices();
container.PerRequest<MainPageViewModel>();
AddCustomConventions();
}
private static void AddCustomConventions()
{
ConventionManager.AddElementConvention<ToggleSwitch>(ToggleSwitch.IsCheckedProperty, "IsChecked", "Click")
.ApplyBinding = (viewModelType, path, property, element, convention) =>
{
//Default binding to "IsChecked" property
if (!ConventionManager.SetBinding(viewModelType, path + ".IsChecked", property, element, convention))
return false;
if (!ConventionManager.HasBinding(element, ToggleSwitch.ContentProperty))
{
var binding = new Binding(path + ".Content");
BindingOperations.SetBinding(element, ToggleSwitch.ContentProperty, binding);
}
return true;
};
}
}
and
bool fixedDistance = true;
public bool FixedDistance
{
get
{
return fixedDistance;
}
set
{
fixedDistance = value;
NotifyOfPropertyChange(() => FixedDistance);
if (fixedDistance)
{
FixedDistanceContent = "Distance";
}
else
{
FixedDistanceContent = "Time";
}
}
}
string fixedDistanceContent;
public string FixedDistanceContent
{
get
{
return fixedDistanceContent;
}
set
{
fixedDistanceContent = value;
NotifyOfPropertyChange(() => FixedDistanceContent);
}
}
where the ToggleSwitch
has the xaml Name=FixedDistance
.
I'm naively (and clearly incorrectly) expecting the ToggleSwitch.IsChecked
to be bound to the FixedDistance
property, and the ToggleSwitch.Content
to be bound to FixedDistanceContent
.
Thanks!
Solution
It looks like this:
ConventionManager.AddElementConvention<ToggleSwitch>(
ToggleSwitch.IsCheckedProperty,
"IsChecked",
"Click");
.ApplyBinding = (viewModelType, path, property, element, convention) =>
{
if (!ConventionManager.SetBinding(viewModelType, path, property, element, convention))
return false;
if (ConventionManager.HasBinding(element, ToggleSwitch.ContentProperty)) return true;
var binding = new Binding(path + "Content") { Mode = BindingMode.TwoWay };
BindingOperations.SetBinding(element, ToggleSwitch.ContentProperty, binding);
return true;
};
does the trick.