hagwmqjgbq
In the previous post about the fillet code I showed a Silverlight demonstration of various connected lines that can be dragged around.
Since binding is a great mechanism to update various elements, and using events is sooo nineties. I implemented a small utility class that does the job.
The issue is that in Silverlight 2 binding between two FrameworkElements is not possible. The workaround is simple but not elegant: you create a intermediate object class that both the frameworks elements can bind to:

Though it’s a simple solution, its also annoying:
Creating an Intermediate class that holds exactly that specific value;
It’s not XAML-able (though you could thing of a construction with an object in the page resources). If you are looking for a in-XAML solution, check out this article by Colin Eberhardt.
So I created a utility class that does the work and is reusable:
The object has four exposed properties and a private Object that got bounded to. Using an Object is very convenient because casting is done by the Binding framework
FrameWorkElement BindingHelper.Source
DependencyProperty BindingHelper.SourcePoperty
FrameWorkElement BindingHelper.Target
DependencyProperty BindingHelper.TargetPoperty
The binding can be made OneWay, by making the binding of the target OneWay, The binding of the source has always to be TwoWay, since I’m using the binding between the Source and the BindingObject in a reverse way: from Source to Object.
After I bound several lines to a single Point, I realised that such an approach was not feasible: the last binding object removed a previous one from the SourceProperty.
So I extended the BindingHelper class to a BindingDispenser that used one Source Framework Element with one SourcePoperty and several Targets.
The Targets Subscribed to the Source-SourcePoperty combination. That works ok, except for the declaration of each of the individual dispensers:
private ElementBindingDispenser Line1StartPoint;
private ElementBindingDispenser Line1EndPoint;
private ElementBindingDispenser Line2StartPoint;
private ElementBindingDispenser Line2EndPoint;
private ElementBindingDispenser Line1MidPoint;
private ElementBindingDispenser Line2MidPoint;
private ElementBindingDispenser RadiusValue;
private ElementBindingDispenser CenterConnectorMidpoint;
private ElementBindingDispenser EndValue;
private ElementBindingDispenser StartValue;
public Page()
{
InitializeComponent();
Line1StartPoint = new ElementBindingDispenser() {Source = MainLine1, SourceProperty = DraggableLineControl.StartPointProperty, AllowContributers = false};
Line1EndPoint = new ElementBindingDispenser() {Source = MainLine1, SourceProperty = DraggableLineControl.EndPointProperty, AllowContributers = false};
Line2StartPoint = new ElementBindingDispenser() {Source = MainLine2, SourceProperty = DraggableLineControl.StartPointProperty, AllowContributers = false};
Line2EndPoint = new ElementBindingDispenser() {Source = MainLine2, SourceProperty = DraggableLineControl.EndPointProperty, AllowContributers = false};
Line1MidPoint = new ElementBindingDispenser() {Source = MainLine1, SourceProperty = DraggableLineControl.MidPointProperty, AllowContributers = false};
Line2MidPoint = new ElementBindingDispenser() {Source = MainLine2, SourceProperty = DraggableLineControl.MidPointProperty, AllowContributers = false};
RadiusValue = new ElementBindingDispenser() { Source = slRadius, SourceProperty = Slider.ValueProperty, AllowContributers = false };
ConnectionLine1.Subscribe(Line1StartPoint, DraggableLineControl.StartPointProperty);
ConnectionLine1.Subscribe(Line2StartPoint, DraggableLineControl.EndPointProperty);
ConnectionLine2.Subscribe(Line1EndPoint, DraggableLineControl.StartPointProperty);
ConnectionLine2.Subscribe(Line2EndPoint, DraggableLineControl.EndPointProperty);
ConnectionLine3.Subscribe(Line1StartPoint, DraggableLineControl.StartPointProperty);
ConnectionLine3.Subscribe(Line2EndPoint, DraggableLineControl.EndPointProperty);
ConnectionLine4.Subscribe(Line1EndPoint, DraggableLineControl.StartPointProperty);
ConnectionLine4.Subscribe(Line2StartPoint, DraggableLineControl.EndPointProperty);
MPConnectionLine1.Subscribe(Line1MidPoint, DraggableLineControl.StartPointProperty);
MPConnectionLine1.Subscribe(Line2MidPoint, DraggableLineControl.EndPointProperty);
MPConnectionLine1.Subscribe(Line1MidPoint, DraggableLineControl.StartPointProperty);
MPConnectionLine1.Subscribe(Line2MidPoint, DraggableLineControl.EndPointProperty);
TheFilletArc.Subscribe(Line1StartPoint, FilletArc.Line1StartProperty);
TheFilletArc.Subscribe(Line1EndPoint, FilletArc.Line1EndProperty);
TheFilletArc.Subscribe(Line2StartPoint, FilletArc.Line2StartProperty);
TheFilletArc.Subscribe(Line2EndPoint, FilletArc.Line2EndProperty);
TheFilletArc.Subscribe(RadiusValue, FilletArc.RadiusProperty);
}
it would be nicer to have a central place to subscribe, and to unsubscribe from.
Something like this:
private void CmdSubscribe_Click(object sender, RoutedEventArgs e)
{
Dispensers.Subscribe(MainLine1, DraggableLineControl.StartPointProperty, TheFilletArc, FilletArc.Line1StartProperty);
Dispensers.Subscribe(MainLine1, DraggableLineControl.EndPointProperty, TheFilletArc, FilletArc.Line1EndProperty);
Dispensers.Subscribe(MainLine2, DraggableLineControl.StartPointProperty, TheFilletArc, FilletArc.Line2StartProperty);
Dispensers.Subscribe(MainLine2, DraggableLineControl.EndPointProperty, TheFilletArc, FilletArc.Line2EndProperty);
Dispensers.Subscribe(slRadius, RangeBase.ValueProperty, TheFilletArc,FilletArc.RadiusProperty);
}
private void CmdUnSubscribe_Click(object sender, RoutedEventArgs e)
{
Dispensers.UnSubscribe(TheFilletArc, FilletArc.RadiusProperty);
}
Unfortunately Silverlight does not provide a way to retrieve binding settings. So UnSubscribing would be a matter of setting the value and thus abandoning the binding.
If Silverlight 3 were years away, it would be a nice concept to work-out and refine further. But as it is, I ‘ll use this as a temporary solution.
If your interested: here’s a zip with the helper classes (NB: not tested for production, just for demo purposes)