ReedCopsey / Gjallarhorn.Bindable

Unidirectional binding library built on top of Gjallarhorn for WPF and Xamarin Forms
MIT License
27 stars 10 forks source link

Binding to the calculated property is occasionally breaks in case when IsSynchronizedWithCurrentItem = true #27

Open FoggyFinder opened 5 years ago

FoggyFinder commented 5 years ago

I faced with odd behaviour:

isSWCI

So, there are not only additional calls of the function update here but also failures of the binding.

I'm not sure is it really a bug in Gjallarhorn.Bindable/Gjallarhorn or this is expected behaviour. But in the last case I would want to know why it happens.

Workaround: exposing immutable object. I.e. in the code below use Seq.toList instead of Seq.toArray.

MCVE:

    <ListBox
        IsSynchronizedWithCurrentItem="True"
        ItemsSource="{Binding TestData}"
        SelectedItem="{Binding Current}" />
open System

[<RequireQualifiedAccess>]
module Views = 
    open FsXaml

    type MainWindow = XAML<"MainWindow.xaml">

open Gjallarhorn.Wpf
open Gjallarhorn.Bindable
open Gjallarhorn.Bindable.Framework

type SomeType = {
    AllData : string
    Current : char
}
with member x.TestData = x.AllData |> Seq.toArray

[<RequireQualifiedAccess>]
type SomeMessages = | SetCurrent of char

let update message model =
    match message with
    | SomeMessages.SetCurrent c ->
        printfn "setCurrent"
        { model with Current = c }

let allData = "test string"
let init = { AllData = allData; Current = allData.[0] }

let appComp : IComponent<SomeType, unit, SomeMessages> =
    Component.create<SomeType, unit, SomeMessages> [
        <@ init.Current @> |> Bind.twoWay (fun m -> m.Current) SomeMessages.SetCurrent
        <@ init.TestData @> |> Bind.oneWay (fun m -> m.TestData)
    ]

let applicationCore nav = Framework.application init update appComp nav

[<EntryPoint>]
[<STAThread>]
let main _ = 
    let navigator = Navigation.singleViewFromWindow Views.MainWindow

    let app = applicationCore navigator.Navigate

    Framework.RunApplication (navigator, app)
    0

code also available in the project IsSynchronizedWithCurrentItemCase here