数据绑定F#视图模型

时间:2013-03-18 11:46:52

标签: wpf xaml f#

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

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

在我的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>

然后识别绑定“消息”。

当我指向类似选区的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

然后我放弃了对绑定消息的识别

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

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

1 个答案:

答案 0 :(得分:6)

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

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

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

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

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