数据绑定F#视图模型

nic*_*las 5 wpf xaml f#

在XAML编辑器中,我可以将命名空间设置为C#项目中包含的Viewmodel

namespace ViewModelDB
{
    public class DependencyViewModel : IViewModelDB
    {
        public string Message { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的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>
Run Code Online (Sandbox Code Playgroud)

然后识别绑定"消息".

当我指向类似选区的F#名称空间时

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
Run Code Online (Sandbox Code Playgroud)

然后我松开了对绑定消息的识别

<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>
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么 ?这是因为Message是接口IDependencyViewModel的实现和F#中接口的显式实现,这是一件好事,但是在这里可以解决这个问题吗?

Tom*_*cek 6

我认为没有比我们在评论中讨论过的更好的解决方案,所以我将其转化为更长的答案.

它不起作用的原因是 - 正如您已经建议的那样 - F#实现了接口,因此Message当它是接口成员时WPF不会看到该属性.最直接的解决方法是将其定义为显式属性(接口实现只能引用main属性):

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

总的来说,我认为推荐用于C#的模式在F#中并不总是很好用.例如,因为F#更简洁(使事情更容易重写)并且更不容易出错(静态捕获更多错误),我认为在这种情况下你可能根本不需要接口.

一个更复杂的解决方法是在运行时使用反射(从显式实现)生成接口的隐式实现,然后将其设置为DataContext但对编辑器不能很好地工作,所以这可能不是一个好的方向.