Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TwoBinding updating issue #74

Closed
felipeleon73 opened this issue Mar 22, 2019 · 6 comments · Fixed by #79
Closed

TwoBinding updating issue #74

felipeleon73 opened this issue Mar 22, 2019 · 6 comments · Fixed by #79

Comments

@felipeleon73
Copy link

felipeleon73 commented Mar 22, 2019

First of all... Thanx for this very nice library!

I have this issue:
I've cloned SubBindings sample and modified with:
-- Program.fs

  • added in the Counter Module
    let setConter value c =
        let a = { c with CounterValue = value + 1 }
        { a with StepSize = c.StepSize + 1 }

  • added to type Msg
    | SetCounter of CounterId * int

  • added to update function
    | SetCounter (cid,value) -> { m with AllCounters = m.AllCounters |> mapCounter cid (Counter.setCounter value) }

  • added to counterBindings

      "CounterValue" |> Binding.twoWay
        (fun (m, c) -> string c.CounterValue)
        (fun v (m, c) -> SetCounter (c.Id, int v))

-- MainWindows.xml

  • modified the textblock showing CounterValue in
    <TextBox Text="{Binding CounterValue}" Width="100" Margin="0,5,10,5" />

Works all but this:
if i insert a number (eg 20) in the textbox and change focus:

  1. the model is update (CounterValue is now 20 and StepSize is now 2)
  2. the StepSize Slider is update to 2
    3. the texbox remain 20 (ISSUE)

now if i hit the "+" button, correctly:

  1. the model is update (CounterValue is now 23 and StepSize remain 2)
  2. the StepSize Slider remain 2
  3. the texbox is updated to 23

Why i've th bold issue?
Thanx
PS sorry for my poor english, i'm italian
(i attach the modified files)
Files.zip

@cmeeren
Copy link
Member

cmeeren commented Mar 22, 2019

As far as I know, WPF doesn't update the value of a control (or at least a TextBox) that has focus, even when PropertyChanged is triggered for the binding source. What seems to happen in this case is that the model update is triggered as (but not after) the TextBox is losing focus, and the TextBox first loses focus after the whole update loop completes. Therefore, the TextBox is not updated with the new model value.

This is supported by the logs: Even after PropertyChanged is fired for CounterValue, the TryGetMember isn't called for that property, which means that the view doesn't try to get the updated value.

In other words: It's just the way WPF works.

@felipeleon73
Copy link
Author

felipeleon73 commented Mar 25, 2019

thanx... Good explanation!
are there possible workarounds for this behavior?

@cmeeren
Copy link
Member

cmeeren commented Mar 25, 2019

I don't know of any simple workarounds. You could try playing around with storing the input value directly in the model and setting the XAML binding trigger to PropertyChanged, and use the LostFocus event to send a different message where you do the transformations you want (example of how to bind to events in #33 (comment)). That's what I do for most input values. For example, for a currency input, I store the raw text value in the model as a string (updating on every keypress), and on LostFocus, I send a different message that formats the string according to currency formatting rules, which updates the value in the TextBox.

@felipeleon73
Copy link
Author

following your suggestions i've tryed to modify the ViewModel Module like this:

  let notifyPropertyChanged propName =
    log "[VM] Triggering PropertyChanged for binding %s" propName
    //propertyChanged.Trigger(this, PropertyChangedEventArgs propName)
    let triggerPropertyChanged = new Action(fun () -> propertyChanged.Trigger(this, PropertyChangedEventArgs propName))
    System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(triggerPropertyChanged) |> ignore

pratically, instead of trigger the propertyChanged directly, i've send it to dispatcher.
now everything works, but I don't know if that causes other (maybe performance) issues

@cmeeren
Copy link
Member

cmeeren commented Mar 25, 2019

Interesting! I'm also unsure what the side-effects of that change is, though it would change how people are used to WPF TextBoxes working, which might not be a good thing. Also it might not always work; there might be a race condition involved when you dispatch it like that. (I don't know the WPF internals well enough to say.)

@cmeeren
Copy link
Member

cmeeren commented Apr 16, 2019

This has been fixed in 2.0.0-beta-10.

@cmeeren cmeeren closed this as completed Apr 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants