2

I am starting to learn F#/Elmish from the top down. I have found alot of information on F#, but very little on moving from C# to F#.

my topmost XAML is:

<Window x:Class="Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Views"
        xmlns:models="clr-namespace:Models;assembly=Models"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <models:Contact/>
    </Window.DataContext>

    <Grid>
        <TabControl ItemsSource="{Binding Details}">
            <TabControl.ItemContainerStyle>
                <Style TargetType="{x:Type TabItem}">
                    <Setter Property="Header" Value="{Binding Name}" />
                </Style>
            </TabControl.ItemContainerStyle>
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type models:ContactDetails}">
                    <local:ContactDetailsView />
                </DataTemplate>
                <DataTemplate DataType="{x:Type models:Internet}">
                    <local:InternetView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type models:PhoneNumbers}">
                    <local:PhoneNumbersView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type models:Addresses}">
                    <local:AddressesView/>
                </DataTemplate>
            </TabControl.Resources>
        </TabControl>
    </Grid>
</Window>

THIS DOES NOT COMPILE.

There are multiple errors here. The "MainWindow" is a C# XAML view.

xmlns:models="clr-namespace:Models;assembly=Models" refers to an F# project (called Models) where ContactDetails is defined as:

namespace Models

module ContactDetails = 
    open System
    open Elmish
    open Elmish.WPF

    /// This is the data model for ContactDetails
    type Model =
        {
            Name: string
            Content: string
            Text: string
        }

    /// This is used to define the initial state of ContactDetails
    let init =
        { Name = "Contact Details"
          Content = "Contact Details Content"
          Text = "Here I Am" }

    /// This is a discriminated union of the available messages from the user interface
    type Msg =
        | None
        | TextInput of string
        | Submit

    /// This is the Reducer Elmish.WPF calls to generate a new model based on a message and an old model
    let update msg m =
        match msg with
        | TextInput s -> { m with Text = s }
        | Submit -> m  // handled by parent
       

    /// Elmish uses bindings() to provide the data context for your view based on a model
    let bindings () : Binding<Model, Msg> list = [
        // One-Way Bindings
        "Name" |> Binding.oneWay (fun m -> m.Content)
        "Content" |> Binding.oneWay (fun m -> m.Content)
    ]

The Internet, phonenumbers, and addresses are defined exactly like the contactdetails.

The Views are all defined in a project (called views -- C#) like:

<UserControl x:Class="Views.ContactDetailsView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="{Binding Content}" />
    </Grid>
</UserControl>

All the views are defined the same way.

So, my newbie questions are really simple:

  1. Although everything compiles without error, at run-time, the clr is unable to locate the "Models" project or file. How to fix this?
  2. Assuming I can get this to recognize the F# project "Models", how do I correctly set the datacontext to an F# module?
  3. What would be an observablecollection to F#? (as in "Details" below?)
  4. Can a DataTemplate be used to address an F# datatype from the C# xaml? If so how?

Any help with these things would be most appreciated as I do best with a top down approach when learning. :)

TIA

Edit#1. Solved the "unable to find file Models". I forgot to add the Models project to the references in the Views project.:(

Alan Wayne
  • 5,122
  • 10
  • 52
  • 95
  • 2
    Have you checked out the Elmish.WPF readme, tutorial, and samples? In particular the tutorial may be useful to understand core MVU and Elmish.WPF concepts. I ask because question 2 and 3 doesn't make sense in light of Elmish.WPF. You don't set the DataContext to a module, and you don't explicitly use ObservableCollections anywhere; Elmish.WPF has several bindings that take care of that. DataTemplates are also covered, e.g. in the SubModelSeq sample. Question 2 and 3 are kind of like "OK I bought an electric screwdriver, but it's much more difficult to turn it than a normal screwdriver." – cmeeren Aug 19 '20 at 19:35
  • @cmeeren I'm sorry :( I have read all I can find on SubModelSeq, but do not see how I can apply different DataTemplates of WPF with data types from F#...any examples would be most appreciated. Thanks. – Alan Wayne Aug 19 '20 at 20:57
  • 2
    Hm, I think I see now what you are asking. Could you post an issue on the Elmish.WPF repo focused on how to use different DataTemplates based on the target type? It may require some non-intuitive workarounds, or Elmish.WPF may actually not support it at the moment, and in the repo there are other people who can pick this up. – cmeeren Aug 20 '20 at 19:24
  • 1
    "I have found...very little on moving from C# to F#." I think the best source is by Scott Walshin https://fsharpforfunandprofit.com/posts/porting-to-csharp-intro/ – Tyson Williams Aug 23 '20 at 19:08
  • Can you share a branch with this code that has the behavior you describe? – Tyson Williams Aug 23 '20 at 19:10
  • @cmeeren Hi. I have posted this issure to Github. As the problem is essentially returning a correct class type for the DataTemplate x:Type instead of an "object", I would hope this would be easy. – Alan Wayne Aug 23 '20 at 20:09

0 Answers0