WPF: Binding

Components of DataBinding in WPF

  1. Binding Target Object: must be a Dependency Object
  2. Target Property: must be a dependency property
  3. Binding Source
  4. Path to the Value

What Triggers a Source Update

Only applicable to TwoWay and OneWayToSource

UpdateSourceTrigger Defines when the value of Source will be updated. Available Options are

  1. LostFocus: When the TextBox control loses focus(Default for Textbox)
  2. PropertyChanged: As you type into the TextBox
  3. Explicit: When the application calls UpdateSource for e.g. when user clicks Save button

    Example of Explicit Binding TextBox binding:

    xml <TextBox x:Name="myTextBox" Text="{Binding MyTextProperty, UpdateSourceTrigger=Explicit}"/>

    Button handler code:

    cs myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

Types of DataBinding in WPF

  • OneWay: Use this when you want the bound property to update the user interface.
  • TwoWay: This has the same behavior as OneWay and OneWayToSource combined. The bound property will update the user interface, and changes in the user interface will update the bound property (You would use this with a TextBox or a Checkbox for example.)
  • OneTime: This has the same behavior as OneWay except it will only update the user interface one time. This should be your default choice for binding (for various reasons I won't elaborate on here), you should only use other types of bindings if you actually need the extra functionality.
  • OneWayToSource: This is the opposite of OneWay -- user interface value changes update the bound property.

What are Value Converters in WPF

Value Converters do data transformation during Binding.

An Example of Value Converter

public class YesNoToBooleanConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    switch(value.ToString().ToLower())
    {
      case "yes":
      case "oui":
        return true;
      case "no":
      case "non":
        return false;
    }
    return false;
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    if(value is bool)
    {
      if((bool)value == true)
        return "yes";
      else
        return "no";
    }
    return "no";
  }
}

Can we Bind multiple values to a single target

Yes, It is called "MultiBinding" and implemented using IMultiValueConverter

MltiBinding in WPF

Example:

public class CustomMultiValueConvertor : IMultiValueConverter
{
  public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    return String.Concat(values[0], " ", values[1]);
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
  {
    return (value as string).Split(' ');
  }
}

And Corrosponding XAML will look like this:

<TextBox x:Name="txtCompleteName">
  <TextBox.Text>
    <MultiBinding Converter="{StaticResource MyCustomConvertor}" UpdateSourceTrigger="PropertyChanged">
      <Binding ElementName="txtFirstName" Path="Text" />
      <Binding ElementName="txtLastName" Path="Text" />
    </MultiBinding>
  </TextBox.Text>
</TextBox>

What is Relative Binding/Relative Soruce

There are four ways of relatively binding in WPF:

  • Self: {Binding RelativeSource={RelativeSource Self}, Path=Name}
  • FindAncestor: Examples

    {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Title}

    {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}, Path=Name}

  • Templated parent

    {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Name}

    {TemplateBinding Name}

  • Current Item of Collection

    {Binding /}

    {Binding Customers/}

    {Binding Customers/Name}

  • Previousdata:

How to capture non click Events using MVVM

We can Capture Keyboard and Mouse events using Input Binding For e.g.

<Window.InputBindings>
  <KeyBinding Key="B"
              Modifiers="Control"
              Command="ApplicationCommands.Open" />
  <KeyBinding Command="ApplicationCommands.Open"
              Gesture="CTRL+R" />
  <MouseBinding Gesture="Control+WheelClick"
              Command="ApplicationCommands.Open" />
  <MouseBinding MouseAction="MiddleClick"
              Command="ApplicationCommands.Cut" />
</Window.InputBindings>

To Bind any event exposed by Dependency Oject to View Model we can use System.Windows.Interactivity e.g.

<Slider
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="ValueChanged">
      <i:InvokeCommandAction
        Command="{Binding MyCommand}"
        CommandParameter="{Binding Text, ElementName=textBox}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Slider>