Showing posts with label UpdateSourceTrigger. Show all posts
Showing posts with label UpdateSourceTrigger. Show all posts

Wednesday, March 5, 2014

Gotcha with StringFormat

Hope most of you have used StringFormat property on your binding to render the formatted value on the user interface. But are you aware about one of its secret. Well before revealing that secret, let’s have a look at how StringFormat works with binding.

Scenario problem: I am taking an example scenario, in which my text box will display amount till three decimals. 

Now there are multiple ways to achieve this. One way can be by using Converters, another way can be by using StringFormat along with TextBox binding. Perhaps there can be more ways apart from these two ;)

In below sample I am going to take StringFormat trick to achieve this and code to perform this operation is very straight forward as:

<TextBox Text="{Binding Amount,StringFormat=f3}" />

With above code, whenever you will lost focus from your TextBox, given amount will be displayed as three decimal points. Till here everything is perfect as expected BUT with one downsize.

Important point on StringFormat: 
What one sees on the screen is not the actual value that will be stored in the storage and can be different from the underlined value. But if this is really a requirement on what we want to show to the user then it’s up to developer to manage such inconsistencies.

Gotcha with StringFormat:
Now time came to know about that GOTCHA. If you want to add UpdateSourceTrigger property = PropertyChanged along with your StringFormat, then guess what will happen???

Code:
<TextBox  Text="{Binding Amount, UpdateSourceTrigger=PropertyChanged, StringFormat=f3}"/>

To understand this issue, let’s go step by step.
Step 1: Run the application and you will get below output.









Step 2: Enter value in the text box as 35.45. You will land up with below screen:









Explanation: Please note, you have applied UpdateSourceTrigger=PropertyChanged. So, as soon as you will hit a keyboard key, immediately StringFormat will be called due to change in target property and sets the underlined source property. Our source property raises a PropertyChanged event that forces the binding to re-bind and re-render based on the StringFormat. 

Problem occurs with fast input scenarios as shown in above screenshot and you will end up with RED rectangle.
Reason: After each key stroke, it is re-rendering the value of a given text box.

Step 3: Click on Save button in order to fire the loose focus from text box as shown below:









Explanation: As per the StringFormat property, given text box should be able to change the value to required precession. But it doesn’t happen. 
Reason: Due to UpdateSourceTrigger=PropertyChanged

One should avoid using UpdateSourceTrigger=PropertyChanged with StringFormat, due to this re-rendering issue.



Saturday, March 1, 2014

UpdateSourceTrigger in WPF

This is a property on a binding that controls the data flow from target to the source and used in two-way databinding scenarios. The default mode is when focus changes but there are number of other options available, which we will see in this article.

Data trigger scenarios:
Let’s talk about some of the data trigger scenarios. By default, modified values in the binding controls only get pushed down when we do activity related to focus change like tab out, minimizing and maximizing window, etc.

·     In some scenarios we want to update values as quickly as possible, or let’s say with every key stoke.  So, to achieve such kind of scenarios Microsoft provided UpdateSourceTrigger

Properties available with UpdateSourceTrigger:
  • Default – This is the default value and it means a lost focus for most of the controls
  • LostFocus – Value updation will be on hold until the focus moves out of control
  • PropertyChanged – Value updation will happen whenever a target property changes. It usually happen on every key stoke
  • Explicit - Used to defer source updates until user do it forcibly by click on any button or so.

Default vs LostFocus 
Default and LostFocus mean the same thing for most of the controls with a exception of DataGrid. For DataGrid:
o                Lost Focus: Cell lost focus
o                Default: Row lost focus

Now let’s have a look at the example and sample code:

    <Grid>
        .........
        <TextBlock Text="Source:" Width="auto"/>
        <TextBox Name="SourceText" Width="160" Height="30" Margin="48,0,44,82" />
        <TextBlock Text="Target:" Grid.Column="1" Width="auto"/>
        <TextBox Name="TargetText" Width="160" Height="30"
                 Grid.Column="1" Margin="44,0,47,82" />
    </Grid>


In above code I am creating 2 TextBlocks and 2 TextBoxes, which will be shown as:







Please note, as of now I haven’t done any binding on my textboxes. As a next step, let’s pick properties of UpdateSourceTrigger and see what each one of does.

Default: When user will change value in Source textbox, value will automatically get updated in Target textbox. BUT when user will modify value in Target textbox, it won’t reflect in Source textbox, until lost focus happens.
Code:
<Grid>
         .......
        <TextBlock Text="Source:" Width="auto"/>
        <TextBox Name="SourceText" Width="160" Height="30" Margin="48,0,44,82" />
        <TextBlock Text="Target:" Grid.Column="1" Width="auto"/>
        <TextBox Name="TargetText" Width="160" Height="30"
                 Text="{Binding ElementName=SourceText, Path=Text,UpdateSourceTrigger=Default}"
                 Grid.Column="1" Margin="44,0,47,82" />
    </Grid>

Output:
When user types in Source TextBox 





When user types in Target TextBox :





LostFocus: As I mentioned earlier, except DataGrid, LostFocus behaves same for all the controls as Default property.

Code:
<Grid>
        .......
        <TextBlock Text="Source:" Width="auto"/>
        <TextBox Name="SourceText" Width="160" Height="30" Margin="48,0,44,82" />
        <TextBlock Text="Target:" Grid.Column="1" Width="auto"/>
        <TextBox Name="TargetText" Width="160" Height="30"
                 Text="{Binding ElementName=SourceText, Path=Text,UpdateSourceTrigger=LostFocus}"
                 Grid.Column="1" Margin="44,0,47,82" />
    </Grid>

Output:
Here output will be same as above case (Default) as it is TextBox.

PropertyChanged: If UpdateSourceTrigger property is set to PropertyChanged, then everytime both Source and Target will be in sync. In another words, updating Source TextBox will update Target TextBox on every key stroke and same proves true if value is updated in Target TextBox.
Code:
<Grid>
         .........
        <TextBlock Text="Source:" Width="auto"/>
        <TextBox Name="SourceText" Width="160" Height="30" Margin="48,0,44,82" />
        <TextBlock Text="Target:" Grid.Column="1" Width="auto"/>
        <TextBox Name="TargetText" Width="160" Height="30"
                 Text="{Binding ElementName=SourceText, Path=Text,UpdateSourceTrigger=PropertyChanged}"
                 Grid.Column="1" Margin="44,0,47,82" />
    </Grid>

Output:
When user types in Source TextBox:





When user types in Target TextBox:





After reading this article, hope you got a clear understanding on UpdateSourceProperty.
Enjoy learning !!!