Coder Social home page Coder Social logo

verbon / winrtmultibinding Goto Github PK

View Code? Open in Web Editor NEW
3.0 2.0 0.0 48 KB

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

C# 100.00%
attached-properties windows-phone winrt multibinding binding windows-8-1 windows-10 uwp twoway oneway

winrtmultibinding's Introduction

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.

<Page xmlns:m="using:WinRTMultibinding.Foundation.Data">
  <Page.Resources>
    <MyMultiValueConverter x:Key="MyMultiValueConverter" />
    <MyConverter x:Key="MyConverter" />
    <SomeDataProvider x:Key="SomeDataProvider" />
  </Page.Resources>
  
  <Button x:Name="MyButton" Content="Button content" />
  
  <TextBlock>
    <m:MultiBindingHelper.MultiBindings>
      <m:MultiBindingCollection>
        <m:MultiBinding TargetProperty="Text" Converter="{StaticResource MyMultiValueConverter}">
          <m:Binding Path="First" Converter="{StaticResource MyConverter}" />
          <m:Binding Path="Second" Source="{StaticResource SomeDataProvider}" />
          <m:Binding Path="Foreground" RelativeSource="{RelativeSource Self}" />
          <m:Binding Path="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:

<TextBlock Text="{Binding Name}">
  <m:MultiBindingHelper.MultiBindings>
    <m:MultiBindingCollection>
      <m:MultiBinding TargetProperty="Text" Converter="{StaticResourc MyMultiValueConverter}">
        <m:Binding Path="First" />
        <m:Binding Path="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:MultiBinding TargetProperty="Text" Converter="{StaticResource MyMultiValueConverter}">
          <m:Binding Path="First" Converter="{StaticResource MyConverter}" />
          <m:Binding Path="Second" Source="{StaticResource SomeDataProvider}" />
          <m:Binding Path="Foreground" RelativeSource="{RelativeSource Self}" />
          <m:Binding Path="Content" ElementName="MyButton" />
        </m:MultiBinding>
      </m:MultiBindingCollection>
    </m:MultiBindingHelper.MultiBindings>
  </TextBlock>
Using StringFormat
<TextBlock>
  <m:MultiBindingHelper.MultiBindings>
    <m:MultiBindingCollection>
      <m:MultiBinding TargetProperty="Text" StringFormat="{}{0} - {1}">
        <m:Binding Path="First" />
        <m:Binding Path="Second" />
      </m:MultiBinding>
    </m:MultiBindingCollection>
  </m:MultiBindingHelper.MultiBindings>
</TextBlock>
Using Converter

Custom converter must implement IMultiValueConverter interface.

public interface IMultiValueConverter
{
    object Convert(object[] values, Type targetType, object parameter, string language);

    object[] ConvertBack(object value, Type[] targetTypes, object parameter, string language);
}
<TextBlock>
  <m:MultiBindingHelper.MultiBindings>
    <m:MultiBindingCollection>
      <m:MultiBinding TargetProperty="Text" Converter="{StaticResource MyMultiValueConverter}">
        <m:Binding Path="First" />
        <m:Binding Path="Second" />
        <m:Binding Path="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:MultiBinding TargetProperty="Text" Mode="TwoWay" Converter="{StaticResource MyMultiValueConverter}">
                <m:Binding Path="First" />
                <m:Binding Path="Second" Mode="OneWay" />
                <m:Binding Path="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:MultiBinding TargetProperty="Text" TargetNullValue="Null value" Converter="{StaticResource MyMultiValueConverter}">
                <m:Binding Path="First" />
                <m:Binding Path="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:MultiBinding TargetProperty="Text" FallbackValue="Fallback value" Converter="{StaticResource MyMultiValueConverter}">
                <m:Binding Path="First" />
                <m:Binding Path="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:

<TextBox x:Name="MyTextBox">
    <m:MultiBindingHelper.MultiBindings>
        <m:MultiBindingCollection>
            <m:MultiBinding TargetProperty="Text" Mode="TwoWay" Converter="{StaticResource MyMultiValueConverter}"
                            UpdateSourceTrigger="Explicit">
                <m:Binding Path="First" />
                <m:Binding Path="Second" />
            </m:MultiBinding>
        </m:MultiBindingCollection>
    </m:MultiBindingHelper.MultiBindings>
</TextBox>

Do this:

var multiBindingExpression = 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:

<Page xmlns:m="using:WinRTMultibinding.Foundation.Data">
  <Page.Resources>
    <MyMultiValueConverter x:Key="MyMultiValueConverter" />
    <GridTypeProvider x:Key="GridTypeProvider" />
  </Page.Resources>
  
  <Grid>
    <Grid.RowDefinitions>
     <RowDefinition />
     <RowDefinition />
     <RowDefinition />
    </Grid.RowDefinitions>
    
    <TextBox Text="Binding to Grid.Row attached property">
      <m:MultiBindingHelper.MultiBindings>
        <m:MultiBindingCollection>
          <m:MultiBinding AttachedPropertyOwnerTypeProvider="{StaticResource GridTypeProvider}" TargetProperty="Row"
                          Converter="{StaticResource MyMultivalueConverter}" Mode="OneWay">
            <m:Binding Path="First" />
            <m:Binding Path="Second" />
            <m:Binding Path="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:

public class GridTypeProvider : 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:

public class MyAttachedPropertyOwnerTypeProvider : TypeProvider<MyAttachedPropertyOwner>
{

}

and set it as AttachedPropertyOwnerTypeProvider for MultiBinding item:

<Page xmlns:m="using:WinRTMultibinding.Foundation.Data">
  <Page.Resources>
    <MyMultiValueConverter x:Key="MyMultiValueConverter" />
    <MyAttachedPropertyOwnerTypeProvider x:Key="MyAttachedPropertyOwnerTypeProvider" />
  </Page.Resources>
  
  <Grid>
    <Grid.RowDefinitions>
     <RowDefinition />
     <RowDefinition />
     <RowDefinition />
    </Grid.RowDefinitions>
    
    <TextBox Text="Binding to Grid.Row attached property">
      <m:MultiBindingHelper.MultiBindings>
        <m:MultiBindingCollection>
          <m:MultiBinding AttachedPropertyOwnerTypeProvider="{StaticResource MyAttachedPropertyOwnerTypeProvider}"
                          TargetProperty="MyAttachedProperty" Converter="{StaticResource MyMultivalueConverter}" Mode="OneWay">
            <m:Binding Path="First" />
            <m:Binding Path="Second" />
            <m:Binding Path="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:MultiBinding TargetProperty="Text" Converter="{StaticResource MyMultiValueConverter}">
              <m:Binding Path="First" />
              <m:Binding Path="Second" />
            </m:MultiBinding>
            <m:MultiBinding TargetProperty="FontSize" Converter="{StaticResource MyAnotherMultiValueConverter}">
              <m:Binding Path="Third" />
              <m:Binding Path="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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.