C# WPF Data Binding and Triggers


This post is a continuation of the previous post on data binding.

From the previous post, when you change the position of the slider, the value in the TextBox is updated immediately. But when you change the value of the TextBox, the slider isn’t updated until the focus in the window changes. The differences in their behavior depend on two factors—the direction of the update and the value of the Binding object’s UpdateSourceTrigger. When you change the text box to 4, as shown below, and press Enter, the slider does not update by slider over to 4. If you press the Tab key the focus of the text box is lost and the slider updates. So, there are differences in their behaviour. The differences in their behavior depend on two factors — the direction of the update and the value of the Binding object’s UpdateSourceTrigger.

DataBinding2

UpdateSourceTrigger

When the direction of the update is from the source to the target, the update always happens immediately. When the direction of the update is from the target to the source, then when the update occurs depends on the value of the UpdateSourceTrigger property of the Binding. Target to source is text box to slider, in this example. In the XAML shown below, the UpdateSourceTrigger is set to PropertyChanged. Now, the slider does not wait for the text box to lose its focus. The slider is updated immediately.

<Window x:Class="BindSlider2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:BindSlider2"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="360">
    <StackPanel>
        <TextBox Margin="10" Name="tbName" Text="{Binding ElementName=sldrSlider, Path=Value, UpdateSourceTrigger=PropertyChanged}"/> 
        <Slider Name="sldrSlider" TickPlacement="TopLeft" Margin="10" Maximum="10"/>
        <Label x:Name="label" Content="Book: Illustrated WPF by Daniel M. Solis, Ch 8 page 196" HorizontalAlignment="Left" Height="26" Margin="10,0,0,0" Width="323"/>
    </StackPanel>
</Window>

Explicit

Another option is illustrated by the window shown below. In this case, the source (slider) is updated only when the Trigger button is clicked.

DataBinding3

<Window x:Class="DataBinding3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataBinding3"
        mc:Ignorable="d"
        Title="MainWindow" Height="180" Width="360">
    <StackPanel>
        <TextBox Margin="10" Name="tbValue" Text="{Binding ElementName=sldrSlider, Path=Value, UpdateSourceTrigger=Explicit}"/>
        <Slider Name="sldrSlider" TickPlacement="TopLeft" Margin="10" Maximum="10"/>
        <Button Click="Button_Click">Trigger</Button>
        <Label x:Name="label" Content="Book: Illustrated WPF by Daniel M. Solis, Ch 8 page 196" HorizontalAlignment="Left" Height="26" Margin="10,0,0,0" Width="323"/>
    </StackPanel>
</Window>

Below is the code you need to write

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DataBinding3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Update the slider (source) with the value in the text box (target)
            // only when the Trigger button is clicked (not immedately
            // and not on loss of focus of text box). To do this
            // get the BindingExpression for the target property
            // and call its UpdateSource method.
            BindingExpression be = tbValue.GetBindingExpression(TextBox.TextProperty);
            be.UpdateSource();
        }
    }
}

In the code-behind, you need to create an event handler for the button, to trigger the explicit update. You accomplish this by getting the BindingExpression for the target property and calling its UpdateSource method

Leave a comment

Your email address will not be published. Required fields are marked *