In this post I describe an update to the Silverlight MultiBinding solution I presented last year. This update includes support for Silverlight 4, attached properties and multiple bindings on a single object.
UPDATE: I have updated this code to include ElementName and TwoWay binding. Grab the latest copy here.
MultiBinding is a WPF feature that allows you to bind a single property to a number of sources, with the source values being combined by a value converter. This is a feature that is missing from Silverlight. About a year ago I developed a MultiBinding solution for Silverlight, which has proven very popular! I even had an email from an Microsoft Attorney asking if they could use it in the Silverlight Facebook client (How cool is that
). I was also very happy when Stefan Olson made a few updates to this code to allow multiple MultiBindings on a single object and spotted the SL4 issue. This blog post is a quick demonstration of these new features …
The following application is an example of MultiBindings in action:
In the above application, the TextBox at the top of the page is bound to both the surname and forename properties of our data-object via converter that takes the first letter of the forename and the surname. If you edit the surname or forename (hitting enter or changing focus to commit), the title is updated automatically. The title tooltip is bound to the all three object properties via a different value converter that concatenates all three.
The XAML for this binding is show below:
<TextBlock x:Name="Block" Foreground="White" FontSize="13" Margin="5,0,0,0"> <local:BindingUtil.MultiBindings> <local:MultiBindings> <local:MultiBinding TargetProperty="Text" Converter="{StaticResource TitleSummaryConverter}"> <local:MultiBinding.Bindings> <local:BindingCollection> <Binding Path="Surname"/> <Binding Path="Forename"/> </local:BindingCollection> </local:MultiBinding.Bindings> </local:MultiBinding> <local:MultiBinding TargetProperty="ToolTipService.ToolTip" Converter="{StaticResource TitleConverter}"> <local:MultiBinding.Bindings> <local:BindingCollection> <Binding Path="Surname"/> <Binding Path="Forename"/> <Binding Path="Age"/> </local:BindingCollection> </local:MultiBinding.Bindings> </local:MultiBinding> </local:MultiBindings> </local:BindingUtil.MultiBindings> </TextBlock>
In the above you can see that our TextBlock has two multibindings, one on Forename and Surname, and the other which includes all three properties. Note, the second multibinding is on the ToolTipService.ToolTip attached property.
You can download the source for Silverlight MultiBinding here: SLMultiBindingUpdate.zip – thanks again to Stefan Olson who added WPF support to this technique.
If you are interested in the technical details of how this works, I refer you to the original article which describes how the code builds a ‘virtual’ branch on the visual tree in order to evaluate your bindings:
I hope this update is of use to SL4 developers. If you have any feedback, please leave a comment below.
You can download the source for Silverlight MultiBinding here: SLMultiBindingUpdate.zip
Regards, Colin E.
Tags: binding, multibinding, silverlight


email: ceberhardt@scottlogic.co.uk



Hi,
Thanks for the good post. But it looked like too much of code to do something simple. We were facing a similar need in one of our projects and we just used a extension method on the item we were binding to and voila, it works just the way we wanted.
Can you tell me why this approach is better than using extension methods?
regards,
Digvijay
How are using an extension method for this? That doesn’t make sense to me since you cannot binding to an extension method. The purpose of this to bind a single property to multiple sources.
Personally I don’t like MultiBinding and IMultiValueConveter because it is not type safe, it has issues with reordering in the XAML, and it lacks compile time checks.
So I am curious what your extension method approach is. Can you elaborate?
I am trying to use your code in this example
http://stackoverflow.com/questions/833943/watermark-textbox-in-wpf
Its complaining the follownig error
A property element cannot be the direct content of another property element.
Any idea how to over come this?
Hi Colin,
I had a situation where I needed to be able to bind to a dictionary and access it from ConvertBack in my Converter. The reason was that I have a dynamic dictionary that I needed to have two-way binding. So I modified your MultiBinding to have a ParamOut dependency property, which gave me a bindable property that I could access on the ConvertBack method. I thought I would share it. I also did the same with Stefan Olson’s version, (the one that allows you to bind to multiple properties on the same data context). The source code can be found here: Source. In addition, I have added a link to my converters, models, and the page it was used in for reference. The AttributePossibleValuesConverter was used in my ItemsSource for the combobox and returns a collection of type AttributePossibleValue, which is a model in my project. The AttributeConverterMultiBinding was the converter I used for my selected item and to get two way binding using multi-binding. I hope this helps someone else out, since it took a couple days to get this all squared away.
Brian
Oh, and I also added the ability to pass in two ConverterParameters, (not bindable).
[...] multibinding: Первое, что вам нужно, это посетить блог scottlogic silverlight multibinding solution for silverlight-4/ – там подробно описано, что и как работает. Я же вам [...]
Great solution, it really worked!
Colin, your solution works like a charm. Thanks for posting!
I have just one question. When I run the application, I get the following error message:
System.Windows.Data Error: ‘MS.Internal.Data.DynamicValueConverter’ converter failed to convert value ‘null’ (type ‘null’); BindingExpression: Path=’ConvertedValue’ DataItem=’SLMultiBinding.MultiBinding’ (HashCode=54023737); target element is ‘System.Windows.Controls.TextBlock’ (Name=’Block’); target property is ‘Visibility’ (type ‘System.Windows.Visibility’).. System.InvalidOperationException: Can’t convert type null to type System.Windows.Visibility.
at MS.Internal.Data.DynamicValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertToTarget(Object value).
What is the reason for this? When I applied the solution to a DataGrid, this message is printed for every row in the grid. Conversions seem to working fine, but curious to find out what is Silverlight complaining about.
I get the same exception.
I fixed it by adding a TargetNullValue dependency property in your MultiBinding class (this issue happens when my DataContext is null obviously) and modifying MultiBindings.Initialize to take TargetNullValue into account when creating the instance of the actual binding.
Thanks for taking the time to share the fix that you found.
Nicolas, can you please share your fix? I am new to bindings.
Thanks.
Read up on DependencyProperty, but still having a hard time understanding your fix. I have added a TargetNullValue dependency property on MultiBinding, but don’t know what to do with it. The error is produced by the following statement in MultiBindings.Initialize:
targetElement.SetBinding(targetDependencyProperty, binding);
At this point targetElement.DataContext is null, but I expect that – my DataContext is set at the UserControl level not at the targetElement level (which happens to be a StackPanel within the UserControl). I would greatly appreciate if you could provide some guidance.
In Initialize, did you create the binding like so:
Binding binding = new Binding(“ConvertedValue”)
{
Source = relay,
Mode = relay.Mode,
TargetNullValue = relay.TargetNullValue
};
Nichoas, in your code below, what is relay.Mode? Relay (MultiBinding) does not have any property named Mode. Aside from that I modified the code as you suggested, but I am still getting the same exception.
[...] http://www.scottlogic.co.uk/blog/colin/2010/05/silverlight-multibinding-solution-for-silverlight-4/ Silverlight Multibinding [...]
This is great but doesn’t build with Warnings As Errors due to _collectionChangedCallback in BindingCollection as it is never assigned. Minor point to an otherwise great contribution. Thanks!
Colin, thank you very much for this great solution!
Could you please publish binaries only so I can include them to my project?
*with strong name, of course
Thanks!
Hi Alex, Sorry … just don’t have time for requests like this. It is easy to do this yourself, just add the files to a class library project and compile it!
very cool stuff, but I’m having some issues using it…looks like only the first value is populated in the object[] value array passed to the converter…all the other ones are null (but the array size is correct) not sure why
@SilverlightDevelopper, @Jonathan Perl,
TwoWay binding and ElementName … here you go:
http://www.scottlogic.co.uk/blog/colin/2010/08/silverlight-multibinding-updated-adding-support-for-elementname-and-twoway-binding/
Hey again Collin !
Any news for that TwoWay MultiBinding ?? ^^
Colin you are the man!
Hello Collin,
One again thank you for this amazing functionality that Silverlight misses a lot.
I have some problems using your solution though because I need a TwoWay binding (Silverlight4), let me explain myself :
I have a product wich has an inventory status. To be compliant with an older software, I need to display this number using a ratio stocked into the said product.
So I have a product which has two property :
product.InventoryStatus (int)
product.Ratio (double)
And, to display it, I use a numericUpDown :
And this is my converter :
public class DecimalStockConverter : IMultiValueConverter
{
private double _ratio = 1;
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double val = System.Convert.ToDouble(values[0] ?? 0);
double ratio = System.Convert.ToDouble(values[1] ?? 0);
while (val > 1)
val /= 10;
_ratio = ratio;
return (val * ratio);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
double val= (_ratio == 0 ? 0 : System.Convert.ToDouble(value ?? 0) / _ratio);
while (val < 1)
val *= 10;
int result = System.Convert.ToInt32(Math.Round(val, 0));
return (new object[] { result, _ratio });
}
}
The problem is : When I change the value of the numericUpDown using the UI, the binding seems to break and I never enter the ConvertBack method. So, does your solution allows a TwoWay MultiBinding ?
If it does, could you please give a sample with an implementation of the convertBack method, I'll may be able to find out what I do wrong !
Thank you !!
@SilverlightDevelopper,
To be honest I have not tried TwoWay binding! I will give it a go and see if a can find / fix this issue.
Colin E.
Great solution!
It is possible to use ElementName with it?
Re: ElementName binding, good idea … I will add that shortly.
(Also thanks for you help for my previous problem, that fixed the issue)
Is there any way to update the code to have ElementName work?
I did a little research in your source code to try and implement it myself but I got pretty lost with the piggy backing and attached properties.
If at all possible it would be extremely helpful!! Thank you.
Does not work for TargetProperty=”datagrid:DataGrid.Columns”.
@Jonathan,
This is because you are binding to an attached property with a namespace prefix. There is no simple way for me to resolve these namespace prefixes, so I make the assumption that attached properties are always in the
System.Windows.Controlsnamespace. You could edit the code at the point where the above namespace is referenced in order to look in the namespace that contains the DataGrid.Hope that helps!
Regards, Colin E.
Hi Colin,
Thanks for sharing – Can this solution do this:
I want to do a String Format (from a resource localisation file) and replace the values like this (this code works in SL4 for a single bind value)
Is it possible to output something similar with your solution, but with multiple bindings, like:
I downloaded and tried it but StringFormat was not recognised.
Thanks for any guidance…
@Rodney,
Sorry – looks like your markup was stripped in the comment. I would like to help, but cannot see your code!
Colin E.
Thanks for the code, I’m suprised it wasn’t included from the start, but I’m having a slight issue with using it with collections.
I’ve created a MultiBinding against the ItemsSource property on a ListBox. I’ve then bound it with two Bindings, one is a collection of entities and the other is an Id field. I then have a converter which filters the collection using the id field.
I have added an item to the collection, however the binding isn’t being updated. I imagine it is potentially an issue with the MultiBinding not checking INotifyCollectionChanged as well as INotifyPropertyChanged? As a workaround I have put MyListBox.GetBindingExpression(ListBox.ItemsSourceProperty).UpdateSource() however this is not causing the breakpoint in my converter to be hit.
Can you advise if this is correct or where I’m going wrong? I’m currently using SL3, however I can’t see that this should have an impact in this area.
Thanks,
Duncan
@Duncan,
The ItemsSource property is a special property which understand the INotifyCollectionChanged interface and responds to its events. The databinding framework is geared towards binding of single properties and responding to PropertyChanged events, so I can see why this would not work. I think the best solution is to create a ViewModel which exposes your filtered collection then bind this to your view.,
Regards, Colin E.
[...] Silverlight MultiBinding solution for Silverlight 4 (Colin Eberhardt) [...]
[...] Silverlight MultiBinding solution for Silverlight 4 (Colin Eberhardt) [...]
Silverlight MultiBinding solution for Silverlight 4 | Colin Eberhardt’s Adventures in WPF…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
[...] Silverlight MultiBinding solution for Silverlight 4 [...]