1

I apologize upfront for all the code following this question. Its included to answer any questions -- I hope.

In Elmish.WPF, I have submodels of submodels of submodels. Each submodel is esentially a list.

That is, I have a main DataGrid, an "AppointmentTable", bound to a Rows list. Each Row has a column list; Each column has a cell list. Lastly each cell is bound to a name.

Updating each of these models takes more time then I am willing to wait. I have two questions; I a mostly interested in the concepts involved:

  1. Can each submodel use Cmd.OfAsync.either where only ONE delay is made when ALL the models are updated and screen updated, and
  2. Would there be any way of running all submodels asynchrounously in parrellel?

TIA

WPF:

 <!--DataContext is MainWindow.fs-->          
            <TabControl ...>
                <TabItem Header="Appointments">
                    <Grid DataContext="{Binding Appointments}">                    
                        <local:Appointments Grid.Column="2" Grid.Row="0" />
                    </Grid>
                </TabItem>
                
                
    

 <!--DataContext from MainWindow ="{Binding Appointments}"-->
    
            <DataGrid Grid.Row="1" x:Name = "AppointmentTable" ItemsSource="{Binding Rows}" ...>
                <DataGrid.Columns>
                    
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid DataContext="{Binding Columns[0]}">
                                    <ListView ItemsSource="{Binding InnerRows}" 
                                      
                                        <ListView.View>
                                            <GridView>
                                                <GridViewColumn Header="First"   Width="100">
                                                    <GridViewColumn.CellTemplate>
                                                        <DataTemplate>
                                                            <TextBlock Text="{Binding Path=FirstName}"/>
                                                            
                                                        </DataTemplate>
                                                    </GridViewColumn.CellTemplate>
                                                </GridViewColumn>

                                                <GridViewColumn Header="Last"  Width="120">
                                                    <GridViewColumn.CellTemplate>
                                                        <DataTemplate>
                                                            <TextBlock Text="{Binding Path=LastName}"/>
                                                            
                                                        </DataTemplate>
                                                    </GridViewColumn.CellTemplate>
                                                </GridViewColumn>

                                                <GridViewColumn Header="Bd" Width="80">
                                                    <GridViewColumn.CellTemplate>
                                                        <DataTemplate>
                                                            <TextBlock Text="{Binding Path=BirthDate}"/>
                                                            
                                                        </DataTemplate>
                                                    </GridViewColumn.CellTemplate>
                                                </GridViewColumn>
                                            </GridView>
                                        </ListView.View>
                                    </ListView>
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
    ----------------------------------------------------------------------------------------------------

F#

module Mainwindow
       type Model =
        { Appointments: Appointments.Model
          ......
        }
   
       // DataContext for Appointments.xaml
    "Appointments" 
        |> Binding.SubModel.required Appointments.bindings
        |> Binding.mapModel (fun m -> m.Appointments)
        |> Binding.mapMsg AppointmentsMsg
        

module Appointments
        type Model =
           { Rows: Row.Model list
             
            }

   "Rows" |> Binding.subModelSeq(
     (fun m -> m.Rows),
     (fun (m, outerRowModel) -> (m.SelectedOuterRow = Some outerRowModel.Id, outerRowModel)),
     (fun (_, outerRowModel) -> outerRowModel.Id),
     RowMsg,
     Row.bindings)                  

module Row =
        type Model =
          { Columns: Column.Model list 
            ...}
            
    "Columns" |> Binding.subModelSeq(
                (fun (_, outerRowModel) -> outerRowModel.Columns),  
                (fun ((b, outerRowModel), columnModel) -> (b && outerRowModel.SelectedColumn = Some columnModel.ColumnId, columnModel)),  
                (fun (_, columnModel) -> columnModel.ColumnId),    
                ColumnMsg,                                   
                Column.bindings)                                

module Column =
       type Model =
        {  Cells: Cell.Model list
          ....
        }
        
    "InnerRows" |> Binding.subModelSeq(
    (fun (_, m) -> m.Cells),
    (fun ((_, m), cellmodel) -> (m.SelectedCellId = Some cellmodel.Id, cellmodel) ),
    (fun (_, cellmodel) -> cellmodel.Id),
    snd,
    Cell.bindings)  
        

module Cell =
        type Model =
            { Id: int
              AppointmentTime: DateTime
              Appointment: Visit option }

      let bindings() = [
        "LastName"  |> Binding.oneWay(fun (_, c) -> 
                                        match c.Appointment with
                                        | Some a -> a.LastName
                                        | None -> ""
                                     )
        "FirstName" |> Binding.oneWay(fun (_, c) -> 
                                        match c.Appointment with
                                        | Some a -> a.FirstName
                                        | None -> ""
                                     )
        "BirthDate" |> Binding.oneWay(fun (_, c) -> 
                                        match c.Appointment with
                                        | Some a -> a.BirthDate.ToShortDateString()
                                        | None -> ""
                                     )
        "ServiceTime" |> Binding.oneWay(fun (_,c) ->
                                          match c.Appointment with
                                          | Some a -> a.EncounterTime
                                          | None -> None
                                       )
        "SelectedLabel" |> Binding.oneWay (fun (b, _) -> if b then " - Selected" else "")
    

]

Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • "Updating each of these models takes more time then I am willing to wait." How long it use taking. Can you share some performance data? Maybe your could share an animated gif of what you are seeing. What change are you making as a user that you think is too slow? – Tyson Williams Jun 09 '22 at 11:49
  • 1
    Take a look at @TysonWilliams 's answer to this question: https://stackoverflow.com/questions/71875622/changing-an-elmish-wpf-model-from-inside-an-async-function – rfreytag Jun 30 '22 at 18:07

0 Answers0