Data Tracking Behind Event Notification - Discussion

Found an interesting problem that I first found in WinForms, and again found it in Silverlight, and most likely WPF when it comes to data binding.

I have a tab control with multiple tabs. When users click on tabs, each time must be valid before allowing the user to switch from the tab.

For example, the user is in a text field that is being updated. Text field bindings are not reset until the control loses focus. Loss of focus occurs when the cursor moves out of a control and focus is assigned to another control.

In this case, the user enters the control (let the text field be used for this example) and updates the text field. At this point, data binding did not lose control, and therefore the VM has not yet seen the change. The user then uses his mouse to click the next tab of the control.

At this point, everything becomes interesting. I used PreviewSelectionChanged (Telerik RadTabControl), since I want to check everything before moving to the next tab, and this also gives me the opportunity to cancel the event.

However, when I look at the virtual machine, in this case it still does not have updated data. I see that the virtual machine is clean, and go ahead and enable the transition to the next tab.

As soon as this event is over, the data is bound and the virtual machine is updated. Now what? Events are not synchronized! When the mouse was used to click the next tab, the text field should have lost focus, redden its bindings before the Preview tab clicks! It's late to bounce back and say that we didn't catch it on time!

I think I found an interesting work on this problem, but I'm not 100% sure that it will work in 100% of cases. I cancel the current event, but then I use the dispatcher and create a delegate pointing to a different method with the same signature as the current event. The dispatcher will add this message to the message pump, which by now (hopefully) now? Will be behind the VM update messages ...

Code Snippet delaying the event

: 1) , , , , , , - .

2) ?

+5
5

, 1:

, , , . , - . , - ( : ..), .

, , . ? click , ( ), , , , .

2:

, UpdateSourceTrigger Explicit, - text_changed .

. , .

, (, ).

+2

: VM PropertyChanged?

protected override void OnThisViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) {
            if(e.PropertyName == "WhateverProperty") {
                //Do your magic here for whatever you want to set
            }
        }

TabItems , , .

<sdk:TabControl>
   <sdk:TabItem IsEnabled="{Binding SomeProperty, Converter={AmIDisabledOrWhatConverter}}" />    
</sdk:TabControl>

, , vm. , vm.

.

+1

, , . , Click . Click .

, , . , .

, . CanExecute true, .

, , Silverlight UpdateSourceTrigger="PropertyChanged" . ().

, , , - , (, , , - Telerik PanelBar), .

+1

, UpdateSourceTrigger = "PropertyChanged".

, , LostFocus.

0
source
    MyOwnTextBox()
    {
        this.TextChanged += (s, e) => UpdateText();
    }

    private void UpdateText()
    {
        BindingExpression be = GetBindingExpression(TextProperty);
        if (be != null && be.ParentBinding.Mode == BindingModes.TwoWay)
        {
            be.UpdateSource();
        }
    }

I use this class, it updates my binding on the fly, however there is a problem with an empty string and null values, if your target property is nullable, then this will update the empty string in the destination property. You can get a workaround using some kind of string converter that will use null instead of an empty string in case of null strings.

0
source

All Articles