2013-03-18 12 views
5

Od edytorze XAML, mogę ustawić nazw do ViewModel zawarte w projekcie C#Databinding do F # ViewModel

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

I w moim 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> 

Wiązanie "Wiadomość" jest następnie uznane.

Kiedy wskazywać na F # nazw o podobnym okręgu

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 

Potem stracenia uznanie Wiadomość wiążącego

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

Czy robię coś źle? Wynika to z tego, że Message jest implementacją interfejsu IDependencyViewModel i jawnej implementacji interfejsów w języku F #, co jest dobre, ale czy jest tutaj, aby obejść to tutaj?

+0

Tak jak mówisz - jest tak prawdopodobnie dlatego, że implementacja interfejsu jest jawna. Typowym obejściem jest proste dodanie właściwości "Message" do samego typu (a implementacja interfejsu może się do niej odwoływać). –

+0

(Myślę, że postępując zgodnie z wytycznymi C# nie działa tak dobrze dla F # + WPF, więc być może można wymyślić lepszy sposób na napisanie kodu.Na przykład, musisz mieć interfejs modelu widoku?) –

+0

Chyba dodanie właściwości jest najbardziej lekkim podejściem. I prawdopodobnie posiadanie interfejsu to przesada. chociaż dla DI jest to całkiem sensowne. – nicolas

Odpowiedz

6

Nie sądzę, że istnieje lepsze rozwiązanie niż to, które omówiliśmy w komentarzach, więc zamieniam to w dłuższą odpowiedź.

Powodem, dla którego nie działa, jest - jak już sugerujesz - że F # implementuje interfejsy jawnie, a więc WPF nie widzi właściwości Message, gdy jest członkiem interfejsu. Najbardziej bezpośrednim obejście jest określenie go jako wyraźnej nieruchomości (oraz wdrożenie interfejsu może tylko odnosić się do budynku głównego):

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

W ogóle uważam, że wzory zalecane dla C# nie zawsze działa dobrze w F # . Na przykład, ponieważ F # jest bardziej zwięzły (łatwiejsze do przepisania) i mniej podatny na błędy (bardziej statyczne przechwytywanie błędów), myślę, że w rzeczywistości nie potrzebujesz interfejsu w tym przypadku.

Bardziej skomplikowanym obejściem byłoby wygenerowanie niejawnej implementacji interfejsu za pomocą refleksji w środowisku wykonawczym (z jawnej implementacji), a następnie ustawienie jej jako DataContext, ale to nie działałoby dobrze z redaktorami, więc może to nie jest dobry kierunek .

+0

masz rację. nie powinniśmy odstraszać i zastrzykiwać uzależnienia wszędzie. DI jest użyteczny, ale przede wszystkim tam, gdzie jesteśmy najbardziej podatni na zmiany. Stanie się to w funkcjonalnym składniku aplikacji, takim jak inny algorytm, pamięć wewnętrzna, itp., Prawdopodobnie nie w widoku. To, że możemy umieścić kilka interfejsów (i chętnie to robimy często) nie oznacza, że ​​powinniśmy je umieszczać wszędzie. – nicolas