2013-03-18 11 views
5

Da l'editor XAML, posso impostare lo spazio dei nomi per il ViewModel contenuta in un progetto C#Databinding un F # viewmodel

namespace ViewModelDB 
{ 
    public class DependencyViewModel : IViewModelDB 
    { 
     public string Message { get; set; } 
    } 
} 

E nella mia 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> 

Il "messaggio" legame è quindi riconosciuto.

Quando io punto ad un F # namespace di circoscrizione simile

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 

Ho poi perdo il riconoscimento del Messaggio vincolante

<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> 

Sto facendo qualcosa di sbagliato? Ciò è dovuto al fatto che il messaggio è un'implementazione dell'interfaccia IDependencyViewModel e l'implementazione esplicita delle interfacce in F #, che è una buona cosa, ma è qui per risolvere il problema?

+0

Come dici tu - questo è probabilmente perché l'implementazione dell'interfaccia è esplicita. La solita soluzione è semplicemente aggiungere una proprietà denominata 'Message' al tipo stesso (e l'implementazione dell'interfaccia può fare riferimento ad essa). –

+0

(Penso che seguire le linee guida C# non funzioni altrettanto bene per F # + WPF, quindi forse puoi trovare un modo migliore per scrivere il codice. Ad esempio, hai bisogno di un'interfaccia vista modello?) –

+0

Immagino aggiungere una proprietà è l'approccio più leggero. E probabilmente avere un'interfaccia è eccessivo. anche se per DI è proprio il punto. – nicolas

risposta

6

Non penso che ci sia una soluzione migliore di quella che abbiamo discusso nei commenti, quindi la trasformo in una risposta più lunga.

Il motivo per cui non funziona è, come già suggerito, che F # implementa esplicitamente le interfacce e quindi WPF non vede la proprietà Message quando è un membro di interfaccia. La soluzione più diretto è quello di definire come una proprietà esplicita (e l'implementazione dell'interfaccia può solo fare riferimento alla proprietà principale):

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 generale, credo che i modelli raccomandati per C# non sempre funzionano bene in F # . Ad esempio, poiché F # è più succinta (rendendo le cose più facili da riscrivere) e meno incline agli errori (rilevando più bug in modo statico), penso che in questo caso non sia effettivamente necessaria un'interfaccia.

Una soluzione più complicata sarebbe quella di generare un'implementazione implicita dell'interfaccia utilizzando reflection in runtime (dall'implementazione esplicita) e quindi impostarla come DataContext ma che non funzionerebbe bene con gli editor, quindi forse non è una buona direzione .

+0

hai ragione. non dovremmo spaventare e mettere l'iniezione della dipendenza ovunque. DI è utile, ma soprattutto dove siamo suscettibili di avere il maggior numero di modifiche. Ciò avverrà nel componente funzionale di un'app, come il diverso algoritmo, il back-end storage, ecc., Probabilmente non in vista. Solo perché possiamo mettere alcune interfacce (e lo facciamo volentieri spesso) non significa che dovremmo metterle ovunque. – nicolas