假设我有一个业务对象(没有AllowNullLiteralAttribute)。
type Person(name: string) =
member val Name = name
override x.ToString() = name和视图模型,所选的人可选地设置。
type MainWindowModel() =
let mutable selectedPerson: Person option = None
:
member val People = ObservableCollection<Person>()
member x.SelectedPerson
with get() = selectedPerson
and set(v) =
if selectedPerson <> v then
selectedPerson <- v
x.RaisePropertyChanged("SelectedPerson")将WPF控件的SelectedItem属性绑定到F#选项属性(不使用AllowNullLiteralAttribute)的最佳方法是什么?
如果我这么做..。
<StackPanel>
<ListBox ItemsSource="{Binding People}"
SelectedItem="{Binding SelectedPerson}"
DisplayMemberPath="Name" />
<TextBlock Text="{Binding SelectedPerson}" />
</StackPanel>...it导致错误,无法将“George”从“Person”类型转换为“Microsoft.FSharp.Core.FSharpOption`1Person”
发布于 2013-07-09 19:38:14
我目前采用的方法是编写自己的IValueConverter。
open System
open System.Globalization
open System.Windows.Data
type OptionsTypeConverter() =
// from http://stackoverflow.com/questions/6289761
let (|SomeObj|_|) =
let ty = typedefof<option<_>>
fun (a:obj) ->
let aty = a.GetType()
let v = aty.GetProperty("Value")
if aty.IsGenericType && aty.GetGenericTypeDefinition() = ty then
if a = null then None
else Some(v.GetValue(a, [| |]))
else None
interface IValueConverter with
member x.Convert(value: obj, targetType: Type, parameter: obj, culture: CultureInfo) =
match value with
| null -> null
| SomeObj(v) -> v
| _ -> value
member x.ConvertBack(value: obj, targetType: Type, parameter: obj, culture: CultureInfo) =
match value with
| null -> None :> obj
| x -> Activator.CreateInstance(targetType, [| x |])然后我的XAML看起来是这样的
<StackPanel>
<ListBox ItemsSource="{Binding People}"
SelectedItem="{Binding SelectedPerson, Converter={StaticResource OptionsTypeConverter1}}"
DisplayMemberPath="Name" />
<TextBlock Text="{Binding SelectedPerson, Converter={StaticResource OptionsTypeConverter1}}" />
</StackPanel>也许还有更简单的方法。此转换器可能已经存在于框架中。可能有更好的实现。
发布于 2013-07-09 20:04:04
我认为使用IValueConverter可能是最干净的方法。
或者,您可以使用选项类型具有Value成员的事实(该成员返回Some的值或为None抛出异常)。因此,如果您知道总是有一个值,或者如果异常没有破坏任何东西(我没有尝试过),那么您可以编写:
<ListBox ItemsSource="{Binding People}"
SelectedItem="{Binding SelectedPerson.Value}"
DisplayMemberPath="Name" />如果异常有问题,则this past SO question suggests使用PriorityBinding
<ListBox ItemsSource="{Binding People}" DisplayMemberPath="Name">
<ListBox.SelectedItem>
<PriorityBinding>
<Binding Path="SelectedPerson.Value" />
<Binding Source="{x:Null}" /> <!-- or some other default... -->
</PriorityBinding>
</ListBox.SelectedItem>
</ListBox>https://stackoverflow.com/questions/17556710
复制相似问题