ReedCopsey / Gjallarhorn.Bindable

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

Bindings`s reset if message updates more than 1 property #33

Open FoggyFinder opened 3 years ago

FoggyFinder commented 3 years ago

MCVE

XAML

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="Sample"
    MinWidth="400"
    MinHeight="100"
    SizeToContent="WidthAndHeight"
    mc:Ignorable="d">
    <ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding CurrentIndex, Mode=TwoWay}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Index}">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsCurrent}" Value="True">
                                    <Setter Property="Foreground" Value="Green" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Window>
open System
open Gjallarhorn.Bindable
open Gjallarhorn.Bindable.Framework
open Gjallarhorn.Wpf
open FsXaml

module Program =    
    type Item = {
        Index : int
        IsCurrent : bool
    }

    type Model = { 
        Items : Item [] ; 
        CurrentIndex : int 
    }

    let initModel i = 
        {
            Items = Array.init i (fun v ->
                {
                    Index = v
                    IsCurrent = false
                }
            )
            CurrentIndex = -1
        }

    type Msg = 
        | Select of int

    let update msg model =
        match msg with
        | Select ind -> 
            let items =
                model.Items
                |> Array.mapi (fun i item ->
                    { item with IsCurrent = i = ind }
                )
            { Items = items; CurrentIndex = ind }

    type ViewModel = 
        {
            Model : Model
            Select : VmCmd<Msg>
        }    

    let d = { Model = initModel 1 ; Select = Vm.cmd (Select 0) }

    let bindToSource =           
        Component.create [
            <@ d.Model.Items @> |> Bind.oneWay (fun m -> m.Items)

            <@ d.Model.CurrentIndex @> 
            |> Bind.twoWay (fun m -> m.CurrentIndex) Msg.Select 
        ]         

    let applicationCore = 
        Framework.application (initModel 5) update bindToSource Nav.empty

type MainWin = XAML<"MainWindow.xaml">

[<STAThread>]
[<EntryPoint>]
let main _ =         
    Framework.RunApplication (Navigation.singleViewFromWindow MainWin, Program.applicationCore)
    1

Expected behaviour:

SelectedItem is highlighten

Current behaviour:

Doesn't seem like any item is selected

gb1


MCVE is artificial but the same happens for more complicated cases. And while the code above can be easily rewritten a real code isn't so easy to change.