Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to achieve focus-reset to update BindingSource of TextBox before any action
    primarykey
    data
    text
    <p>I have observed some unexpected or at least not-perfectly-matching-my-needs behaviour of textboxes bound to textproperties when I can't use using UpdateTrigger=PropertyChanged for my binding. Probably it is not an issue with the textbox but will occur with other editors as well.</p> <p>In my example (source code attached), I have a WPF TabControl bound to some collection. On each tab, you can edit an item from the collection, in various ways you can trigger a save-action, which should save the edits to some model. The textboxes bound to each items' properties are (on purpose) kept to default update-trigger 'OnFocusLost'. This is because there is some expensive validation taking place when a new value is set.</p> <p>Now I found there are at least two ways to trigger my save-action in such a way, that the last focused textbox does not update the bound value. 1) Changing the tab-item via mouse-click on its header and then clicking some save-button. (changing back to the previous tab shows that the new value is even lost) 2) Triggering the save-command via KeyGesture.</p> <p>I setup an example application that demonstrates the behaviour. Clicking on "Save All" will show all item values, the other save-button only shows the current item.</p> <p><strong>Q:</strong> What would be the best way to make sure that all bindingsources of all my textboxes will be updated before the bound objects are comitted? Preferably there should be a single way that catches all possibilites, I dislike to catch each event differently, since I would worry to have forgotten some events. Observing the selection-changed-event of the tab-control for example would solve issue 1) but not issue 2).</p> <p>Now to the example:</p> <p>XAML first:</p> <pre><code>&lt;Window x:Class="TestOMat.TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:TestOMat="clr-namespace:TestOMat" Title="TestOMat" x:Name="wnd"&gt; &lt;Grid&gt; &lt;Grid.Resources&gt; &lt;DataTemplate x:Key="dtPerson" DataType="{x:Type TestOMat:Person}"&gt; &lt;StackPanel Orientation="Vertical"&gt; &lt;StackPanel.CommandBindings&gt; &lt;CommandBinding Command="Close" Executed="CmdSaveExecuted"/&gt; &lt;/StackPanel.CommandBindings&gt; &lt;TextBox Text="{Binding FirstName}"/&gt; &lt;TextBox Text="{Binding LastName}"/&gt; &lt;Button Command="ApplicationCommands.Stop" CommandParameter="{Binding}"&gt;Save&lt;/Button&gt; &lt;/StackPanel&gt; &lt;/DataTemplate&gt; &lt;/Grid.Resources&gt; &lt;Grid.RowDefinitions&gt; &lt;RowDefinition/&gt; &lt;RowDefinition/&gt; &lt;/Grid.RowDefinitions&gt; &lt;Grid.CommandBindings&gt; &lt;CommandBinding Command="ApplicationCommands.Stop" Executed="CmdSaveAllExecuted"/&gt; &lt;/Grid.CommandBindings&gt; &lt;TabControl ItemsSource="{Binding ElementName=wnd, Path=Persons}" ContentTemplate="{StaticResource dtPerson}" SelectionChanged="TabControl_SelectionChanged"/&gt; &lt;Button Grid.Row="1" Command="ApplicationCommands.Stop"&gt;Save All&lt;/Button&gt; &lt;/Grid&gt;&lt;/Window&gt; </code></pre> <p>And the corresponding class</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; namespace TestOMat { /// &lt;summary&gt; /// Interaction logic for TestOMat.xaml /// &lt;/summary&gt; public partial class TestWindow : Window { public TestWindow() { InitializeComponent(); } private List&lt;Person&gt; persons = new List&lt;Person&gt; { new Person {FirstName = "John", LastName = "Smith"}, new Person {FirstName = "Peter", LastName = "Miller"} }; public List&lt;Person&gt; Persons { get { return persons; } set { persons = value; } } private void CmdSaveExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) { Person p = e.Parameter as Person; if (p != null) { MessageBox.Show(string.Format("FirstName={0}, LastName={1}", p.FirstName, p.LastName)); e.Handled = true; } } private void CmdSaveAllExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) { MessageBox.Show(String.Join(Environment.NewLine, Persons.Select(p=&gt;string.Format("FirstName={0}, LastName={1}", p.FirstName, p.LastName)).ToArray())); e.Handled = true; } private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { Console.WriteLine(String.Format("Selection changed from {0} to {1}", e.RemovedItems, e.AddedItems)); // Doing anything here only avoids loss on selected-tab-change } } public class Person { public string FirstName { get; set; } public string LastName { get; set; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload