Saturday, January 10, 2009

Bind to many method simultaneously. Binding in WPF part 2.

Download source files - here
Download binary files - here

Target:
We have some views that have as source one shared collection. They are located in any ItemsControls (ListBoxs in my case). Those views pass form different parametrized methods (we use the ObjectDataProvider and bind to a method possibility for this purposes). How can we implement one control element's property for affect on those views? We have restricts - it is needed to make in XAML code.

Problem:
How can we pass a value of control element as parameter in bind to a methods?

Solution:
First of all we should declare some (I used "two", so I will write in next time "two" instead of "some") ObjectDataProvider objects.

<ObjectDataProvider ObjectType="{x:Type local:CItems}"
MethodName="GetMax" x:Key="max" >
<ObjectDataProvider.MethodParameters>
<system:Int32>3</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

<ObjectDataProvider ObjectType="{x:Type local:CItems}"
MethodName="GetMin" x:Key="min" >
<ObjectDataProvider.MethodParameters>
<system:Int32>3</system:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

Bind those objects to views:

<ListBox ItemsSource="{Binding Source={StaticResource min}}" />
<ListBox ItemsSource="{Binding Source={StaticResource max}}" />

Now we need to create a binding to control element's property that has affect to both those data provider. We use MultiBinding with Mode is set OneWayToSource for this purpose. We should implement Converter of MultiBinding. Since we set Mode as OneWayToSource we need only ConvertBack method:

public Object[] ConvertBack( Object value, Type[] targetTypes, Object parameter, CultureInfo culture )
{
Int32 cnt = targetTypes.Length;
Object[] result = new Object[ cnt ];
String str = value.ToString();

if( !String.IsNullOrEmpty( str ) )
{
Int32 index = Int32.Parse( value.ToString() );

for( Int32 i = 0; i < cnt; ++i )
{
result[ i ] = index;
}
}

return result;
}

Note: We should unbox value to Int32 other case value isn't correctly passed to method of data provider.

Now we can easy implement this MultiBinding our XAML code:

<ComboBox.Text>
<MultiBinding Mode="OneWayToSource" Converter="{StaticResource artfull}">
<Binding Source="{StaticResource max}"
Path="MethodParameters[0]"
BindsDirectlyToSource="true"
UpdateSourceTrigger="PropertyChanged"
/>
<Binding Source="{StaticResource min}"
Path="MethodParameters[0]"
BindsDirectlyToSource="true"
UpdateSourceTrigger="PropertyChanged"
/>
</MultiBinding>
</ComboBox.Text>

Now when Text property of ComboBox is changed that views will be updated. Easy and nice :). If some details isn't clear - source and binary files were attached in the beginning of article.