Databinding a F# viewmodel

f#, wpf, xaml

Solution

I don't think there is a better solution than the one we discussed in comments, so I'm turning that into a longer answer.

The reason why it does not work is - as you already suggested - that F# implements interfaces explicitly and so WPF does not see the `Message` property when it is an interface member. The most direct workaround is to define it as an explicit property (and the interface implementation can just refer to the main property):

type DependencyViewModel () = 
    member val Message = "" with get, set
    interface IDependencyViewModel with 
        member x.Message with get() = x.Message and set(v) = x.Message <- v

In general, I think the patterns recommended for C# do not always work nicely in F#. For example, because F# is more succinct (making things easier to rewrite) and less error-prone (catching more bugs statically), I think you might not actually need an interface in this case at all.

A more complicated workaround would be to generate an implicit implementation of the interface using reflection at runtime (from the explicit implementation) and then set it as `DataContext` but that would not work nicely with editors, so maybe that's not a good direction.

Problem

From the XAML editor, I can set the namespace to the Viewmodel contained in a C# project ``` namespace ViewModelDB { public class DependencyViewModel : IViewModelDB { public string Message { get; set; } } } ``` And in my xaml ``` <UserControl 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" xmlns:ViewModelDB="clr-namespace:ViewModelDB;assembly=ViewModelDB" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" > <UserControl.DataContext> <ViewModelDB:DependencyViewModel/> </UserControl.DataContext> <Grid> <TextBlock Text="{Binding Message}"/> </Grid> </UserControl> ``` The binding "Message" is then recognized. When I point at a F# namespace of similar constituency ``` namespace ModuleDBGraph open Infrastructure open Microsoft.Practices.Prism.Regions; open Microsoft.Practices.Unity; type IDependencyViewModel = inherit IViewModel abstract Message : string with get, set type DependencyViewModel () = interface IDependencyViewModel with member val Message = "" with get, set ``` I then loose the recognition of the binding Message ``` <UserControl 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" xmlns:ViewModelDB="clr-namespace:ViewModelDB;assembly=ViewModelDB" xmlns:ViewModelDBFS="clr-namespace:ModuleDBGraph;assembly=ViewModelDBGraphFS" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" > <UserControl.DataContext> <ViewModelDBFS:DependencyViewModel/> </UserControl.DataContext> <Grid> <TextBlock Text="{Binding Message}"/> </Grid> </UserControl> ``` Am I doing something wrong ? This is due to Message being an implementation of the interface IDependencyViewModel and explicit implementation of interfaces in F#, which is a good thing, but is there away to work around this here ?

Original source