我如何将数据绑定到XAML中的联合案例值?
目前,数据绑定值指向String20对象,而不是union情例(即String20)所包含的实际字符串值。
示例:
<ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First" />
作者定义:
type Name = {
First:String20
Last:String20
Suffix:String20 option
}
type Module = {
Author:Name
Duration:Duration
}
XAML:
<Window x:Class="Client.MainWindow"
...
xmlns:manageModules="clr-namespace:ManageModules;assembly=ManageModules">
<Window.DataContext>
<manageModules:CreationViewModel />
</Window.DataContext>
<Grid>
<ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First"
TextElement.Foreground="LightBlue" Background="Black" />
</Grid>
</Window>
视图模型:
namespace ManageModules
...
type CreationViewModel() =
inherit ViewModelBase()
let name = { First=String20("Scott"); Last=String20("Nimrod"); Suffix=None }
let duration = { Hours=1; Minutes=30; Seconds=0 }
let moduleItem = { Author=name; Duration=duration }
let mutable (_modules:Module ObservableCollection) = ObservableCollection()
do _modules.Add(moduleItem)
member this.Modules
with get() = _modules
and set(value) = _modules <- value
member this.Add moduleItem =
_modules.Add(moduleItem)
业务范围:
module ManageModule.Entities
type Duration = {
Hours:int
Minutes:int
Seconds:int
}
type String20 = String20 of string
type Name = {
First:String20
Last:String20
Suffix:String20 option
}
type Module = {
Author:Name
Duration:Duration
}
and Section =
| Introduction of Module
| Conclusion of Module
| Content of Module list
答案 0 :(得分:6)
我的建议是修改String20
,使其包含一个普通string
值的附加成员 - 然后您可以绑定到普通的string
成员。
要将成员添加到类型,您可以写:
type String20 =
| String20 of string
member this.Value =
let (String20(str)) = this
str
然后你应该写:
<ListView ItemsSource="{Binding Modules}" DisplayMemberPath="Author.First.Value" />
可能有更复杂的方法来解决这个问题 - 我猜WPF有一些机制来指定在幕后绑定中发生的转换 - 但添加Value
作为成员可能是一个很好的简单开始。
答案 1 :(得分:0)
另一种方法是使用Tomas暗指的ValueConverter。
这个例子是用C#编写的。后来,当我找到更多时间时,我将使用F#演示相同的方法。
我更喜欢在域逻辑中保持简洁性,而不是让UI或数据存储框架规定(即将人质)域逻辑。
因此,我使用C#提供了以下值转换器:
using System;
using System.Globalization;
using System.Windows.Data;
using static ManageModule.Entities;
namespace Client.Converters
{
public class String20Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var unionCase = value as String20;
return unionCase.Item;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
更新的XAML如下所示:
<Window x:Class="Client.MainWindow"
...
xmlns:local="clr-namespace:Client"
xmlns:manageModules="clr-namespace:ManageModules;assembly=ManageModules"
xmlns:converters="clr-namespace:Client.Converters"
mc:Ignorable="d"
Background="Black"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<manageModules:CreationViewModel />
</Window.DataContext>
<Window.Resources>
<converters:String20Converter x:Key="String20Converter" />
</Window.Resources>
<Grid>
<ListView ItemsSource="{Binding Modules}" Background="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Author.First, Converter={StaticResource String20Converter}}"
Foreground="LightBlue" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
请注意我们如何保留原始域逻辑:
type Duration = {
Hours:int
Minutes:int
Seconds:int
}
type String20 = String20 of string
type Name = {
First:String20
Last:String20
Suffix:String2
}