1

我在 ViewModel 类上定义了一个名为的静态属性

static member GetColumnTypes = FSharpType.GetUnionCases typeof<ColumnType>

其中 ColumnType 是普通的联合类型

type ColumnType   = T_Link of TableName | T_Real | T_Bool | T_Int | T_String

我不明白 XAML 在以下情况下绑定到此类集合的逻辑:

<UserControl.Resources>
  <ObjectDataProvider x:Key="typelist" MethodName="GetColumnTypes" ObjectType="{x:Type local:MarkupViewModel}"/>
  <local:MarkupViewModel x:Key="defaultVM" d:IsDataSource="True"/>
</UserControl.Resources>

  //1-WORKS
  <ComboBox ItemsSource="{Binding Source={StaticResource defaultVM}, Path=GetColumnTypes}"></ComboBox> 

  //2-DOES NOT WORK
  <ComboBox ItemsSource="{Binding Source={StaticResource typelist}}"></ComboBox>

  //3-DOES NOT WORK
  <ComboBox ItemsSource="{Binding Source={x:Type local:MarkupViewModel}, Path=GetColumnTypes}"></ComboBox>

  //4-WORKS
  <ComboBox ItemsSource="{Binding  Path=GetColumnTypes}" />
  1. 为什么这行得通?我虽然命名的静态资源defaultVM是使用无参数构造函数创建一个对象。在这个对象上,没有 GetColumnTypes 方法!
  2. 为什么它不起作用?我以为我在调用GetColumnTypes指定的类型。如果我看一下获取 Enum values 的示例,这似乎就是正在发生的事情。我的情况更简单,因为它没有参数
  3. 同样,这不是在提到的类型上调用 he 方法吗?
  4. 在这里,我将 datacontext 设置为我的 Viremodel 的一个实例,它“神奇地”知道 hos 从实例转到静态方法。

除了这些问题,我觉得它非常像黑盒魔法,我看到的关于绑定过程的信息很少。

说清楚的最佳方法是什么?
绑定过程可能有一些调试工具可用吗?

4

1 回答 1

3

There are two things to know that should clear things up:

First, in XAML, you can access static members through an instance of the type. You can also do this in VB.NET, for instance with this code:

Dim x = New MarkupViewModel()
x.GetColumnTypes
MarkupViewModel.GetColumnTypes

The last two lines are equivalent. In fact, the compiler rewrites the first line as the second. XAML is the same way. If you have an instance, you can access a static member through the same syntax as an instance member. (Other languages, like C# and F#, don't allow this syntax).

Second, ObjectDataProvider calls a method, but GetColumnTypes is a property. If you had defined it as static member GetColumnTypes() = ... I would expect it to work.

However, none of these approaches are really ideal. What you want to do is use the x:Static markup extension. This is what it was designed for.

In your namespace definitions (in the topmost tag of the XAML file), write something like this:

<UserControl [...] xmlns:local="clr-namespace:Your.Namespace">

And then have the combo box declare its items like this:

<ComboBox ItemsSource="{x:Static local:MarkupViewModel.GetColumnTypes}">

(although if you're keeping it as a property and not a function you should of course rename it as ColumnTypes not GetColumnTypes)

Oh, and as for diagnosing binding errors, quite a lot of debugging information is available through Visual Studio Options > Debugging > Output Window > WPF Trace Settings, which can dump a lot of information to the output window. However they can be somewhat difficult to interpret if you don't know WPF very well. An excellent general-purpose WPF utility is Snoop, which is good for many other reasons, but it can also display binding error information.

于 2013-03-28T04:12:25.417 回答