Skip to content

Latest commit

History

43 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

WinRTMultiBinding

Provides MultiBinding functionality for Windows 8.1, Windows Phone 8.1, Windows 10 UWP projects.

WinRT MultiBinding supports most of WPF MultiBinding's features.

Installation via NuGet package

This portable library is available as NuGet package for Windows 8.1, Windows Phone 8.1, Windows 10 UWP projects:

https://www.nuget.org/packages/WinRTMultibinding.Universal/1.0.0

Use Package Manager to install package or type the following into the Package Manager Console:

Install-Package WinRTMultibinding.Universal

Installing obsolete packages

This library is also available as obsolete NuGet packages for Windows and Windows Phone projects:

https://www.nuget.org/packages/WinRT-Multibinding-Windows/

https://www.nuget.org/packages/WinRT-Multibinding-WindowsPhone/

Use Package Manager to install packages or type the following into the Package Manager Console:

Install-Package WinRT-Multibinding-Windows
Install-Package WinRT-Multibinding-WindowsPhone

NOTE: As these packages are obsolete, they are no longer supported. So, you should better install portable library version described above for use in your Windows 8.1/Windows Phone 8.1 projects.

General

This library provides you MultiBindingHelper.MultiBindings attached property which you should initialize with a MultiBindingCollection instance which you should populate with MultiBinding items. Instance of MultiBinding class hosts Binding items.

<Pagexmlns:m="using:WinRTMultibinding.Foundation.Data">
<Page.Resources>
<MyMultiValueConverterx:Key="MyMultiValueConverter" />
<MyConverterx:Key="MyConverter" />
<SomeDataProviderx:Key="SomeDataProvider" />
</Page.Resources>
<Buttonx:Name="MyButton"Content="Button content" />
<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First"Converter="{StaticResource MyConverter}" />
<m:BindingPath="Second"Source="{StaticResource SomeDataProvider}" />
<m:BindingPath="Foreground"RelativeSource="{RelativeSource Self}" />
<m:BindingPath="Content"ElementName="MyButton" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
</Page>

Features

  • Various Sources (ElementName, Source, RelativeSource, DataContext)
  • StringFormat
  • Converter
  • TargetNullValue
  • FallbackValue
  • Different Modes (OneTime, OneWay, TwoWay)
  • UpdateSourceTrigger
  • Attached properties binding

Restrictions

  1. RelativeSource.TemplatedParent and RelativeSouce.None are not yet supported.

  2. UpdateSourceTrigger - There are only PropertyChanged and Explicit modes. PropertyChanged is set by default. To update source explicitly use GetMultiBindingExpression() extension method. It returns MultiBindingExpression object which has UpdateSource() method.

  3. As you can see, you do not set directly MultinBinding instance to target property, but use attached property instead. So, there are no restrictions to set built-in single Binding to the same property, but this binding will be ignored. For example if you do this:

<TextBlockText="{Binding Name}">
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Converter="{StaticResourc MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>

In this case Text="{Binding Name}" binding will be ignored.

Examples

Sources

As you've seen above WinRTMultiBinding supports different binding sources. But: RelativeSource supports only Self mode.

<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First"Converter="{StaticResource MyConverter}" />
<m:BindingPath="Second"Source="{StaticResource SomeDataProvider}" />
<m:BindingPath="Foreground"RelativeSource="{RelativeSource Self}" />
<m:BindingPath="Content"ElementName="MyButton" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
Using StringFormat
<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"StringFormat="{}{0} - {1}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
Using Converter

Custom converter must implement IMultiValueConverter interface.

publicinterfaceIMultiValueConverter{objectConvert(object[]values,TypetargetType,objectparameter,stringlanguage);object[]ConvertBack(objectvalue,Type[]targetTypes,objectparameter,stringlanguage);}
<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
<m:BindingPath="Third" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
Modes

MultiBinding's BindingMode(OneWay by default) used as the default value for all the bindings in the collection unless an individual binding overrides this property. For example, if the Mode property on the MultiBinding object is set to TwoWay, then all the bindings in the collection are considered TwoWay unless you set a different Mode value on one of the bindings explicitly. Child bindings can only limit parent Mode, but not vice versa(it's okay to have MultiBinding's Mode set to TwoWay and one of the Bindings Mode set to OneWay, but NOT MultiBinding's Mode set to OneWay and one of the Bindings Mode set to TwoWay).

<TextBox>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Mode="TwoWay"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second"Mode="OneWay" />
<m:BindingPath="Third" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBox>
TargetNullValue

If you specify TargetNullValue it's returned when your Converter returns null.

<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"TargetNullValue="Null value"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
FallbackValue

If you specify FallbackValue it's returned when:

  • you specified both StringFormat and Converter to target string property
  • your Converter returned null, but TargetNullValue is not specified
  • your Converter returned DependencyProperty.UnsetValue

If you did not specify FallbackValue it contains target property type's default value. So, it's always initialized.

<TextBlock>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"FallbackValue="Fallback value"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBlock>
UpdateSourceTrigger

If you chose Default or PropertyChanged, your source value is updated every time target property changes. If you chose Explicit:

<TextBoxx:Name="MyTextBox">
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Mode="TwoWay"Converter="{StaticResource MyMultiValueConverter}"UpdateSourceTrigger="Explicit">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBox>

Do this:

varmultiBindingExpression=MyTextBox.GetMultiBindingExpression(TextBox.TextProperty);multiBindingExpression.UpdateSource();
Attached properties binding

To bind to attached property you should specify AttachedPropertyOwnerTypeProvider, and set TargetProperty to target property name without attached property owner type name. So, binding to Grid.Row attached property will look as folowing:

<Pagexmlns:m="using:WinRTMultibinding.Foundation.Data">
<Page.Resources>
<MyMultiValueConverterx:Key="MyMultiValueConverter" />
<GridTypeProviderx:Key="GridTypeProvider" />
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBoxText="Binding to Grid.Row attached property">
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingAttachedPropertyOwnerTypeProvider="{StaticResource GridTypeProvider}"TargetProperty="Row"Converter="{StaticResource MyMultivalueConverter}"Mode="OneWay">
<m:BindingPath="First" />
<m:BindingPath="Second" />
<m:BindingPath="Third" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBox>
</Grid>
</Page>
Introducing Type Providers

In the previous example GridTypeProvider is a class derived from TypeProvider<T> abstract class. This class has method GetType which returns the type of its generic type parameter (explicit implementation of ITypeProvider interface). The only purpose of this class, as you can see, is to provide attached property owner type. You only need to inherit from TypeProvider<T> with an attached property owner type specified as a generic type parameter, so that later you can use it in XAML. GridTypeProvider might look like this:

publicclassGridTypeProvider:TypeProvider<Grid>{}

Then you should instantiate it in XAML and pass as a value for AttachedPropertyOwnerTypeProvider property, as shown in the example above.

Type Providers based solution overview

This awkward and clumsy interface based on type providers might not seem clear at a first glance. But it has the greatest advantage: it's type and assembly independent. This means it allows you to bind not only to built-in controls (such as Grid, Scrollviewer) which have attached properties, but also to custom attached properties hosted by custom types.

For example, if we would like to bind to MyAttachedProperty property which is hosted by MyAttachedPropertyOwner class, we should simply derive from TypeProvider<T> in the following manner:

publicclassMyAttachedPropertyOwnerTypeProvider:TypeProvider<MyAttachedPropertyOwner>{}

and set it as AttachedPropertyOwnerTypeProvider for MultiBinding item:

<Pagexmlns:m="using:WinRTMultibinding.Foundation.Data">
<Page.Resources>
<MyMultiValueConverterx:Key="MyMultiValueConverter" />
<MyAttachedPropertyOwnerTypeProviderx:Key="MyAttachedPropertyOwnerTypeProvider" />
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBoxText="Binding to Grid.Row attached property">
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingAttachedPropertyOwnerTypeProvider="{StaticResource MyAttachedPropertyOwnerTypeProvider}"TargetProperty="MyAttachedProperty"Converter="{StaticResource MyMultivalueConverter}"Mode="OneWay">
<m:BindingPath="First" />
<m:BindingPath="Second" />
<m:BindingPath="Third" />
</m:MultiBinding>
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBox>
</Grid>
</Page>

So this weird interface is payment for allowing you binding to any attached property you want.

Pros:

  • possibility to bind to any attached property hosted by any type

Cons:

  • cumbersome, clumsy interface (which is fixable by good code styles, naming conventions etc.)
Multiple properties binding

Simply add several MultiBinding items to MultiBindingCollection.

<TextBox>
<m:MultiBindingHelper.MultiBindings>
<m:MultiBindingCollection>
<m:MultiBindingTargetProperty="Text"Converter="{StaticResource MyMultiValueConverter}">
<m:BindingPath="First" />
<m:BindingPath="Second" />
</m:MultiBinding>
<m:MultiBindingTargetProperty="FontSize"Converter="{StaticResource MyAnotherMultiValueConverter}">
<m:BindingPath="Third" />
<m:BindingPath="Fourth" />
</m:MultiBindingCollection>
</m:MultiBindingHelper.MultiBindings>
</TextBox>

Support

If you do have a contribution for the package feel free to put up a Pull Request or open Issue.

About

Provides MultiBinding functionality for Windows 8.1 and Windows Phone 8.1 projects.

Topics

Resources

Stars

3 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages