"{Binding Path=.}"和"{Binding}"是否真的相等?

54

在我的WPF项目中,我有一个ListBox来显示来自List<string>集合的项。我想让这些项的文本可编辑,因此我使用了一个ItemTemplate将它们包装在一个TextBox中(可能不是最好的方法,但我是WPF新手)。我一直无法将TextBoxes的Text属性简单地绑定到每个项的值。最后,我偶然发现了一个例子,它在Path属性中使用了一个点号或句点({Binding Path=.}):

<ListBox ItemsSource="{Binding ElementName=recipesListbox,Path=SelectedItem.Steps}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Path=.}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
然而我不明白为什么简单地使用{Binding}并不起作用。根据微软的说法,它引发了“双向绑定需要Path或XPath”异常:[...] 使用点(.)路径可以绑定到当前源。例如,Text =“{Binding}”等同于Text =“{Binding Path =.}”。有人能解释一下这种模糊的行为吗?此外,似乎{Binding Path=.}并不一定会产生双向绑定,因为修改文本并移动焦点不会更新底层源(同一源还在DataGrid控件上显示和成功修改属性)。我肯定是错过了什么。
4个回答

34

异常的点在于您不能双向绑定一个数据源本身,因此它试图防止您创建不按您预期运行的绑定。通过使用 {Binding Path=.},您可以欺骗错误检测。

(此外,文档错误或不准确并非闻所未闻,尽管我通常非常喜欢MSDN文档,因为它通常包含人们感兴趣的关键点)


4
这是正确的答案。我刚刚自己遇到了这个现象。 - Allon Guralnek
1
但是双向绑定仍然失败。它拒绝保存更改。如果您有一个 ObsColl<int>,并执行 Path=. Mode=TwoWay 绑定,则添加到集合中将正常工作。例如,更改索引 0 处的数字不会起作用。如果您将 datagrid 绑定到它并指定 datagridtextcolumn,则无法使用 Path=. 进行保存。 - user99999991
@user999999928:这就是我一直在说的:你只是欺骗了错误处理。你制造了一个不被检测到的错误,但你仍然无法得到所需的绑定,因为你仍然绑定到无法检测到更改的源。 - H.B.

23
文档说明{Binding}等效于{Binding Path=.}。然而,它与您键入的{Binding Path}并不相同。如果包括Path属性,您必须将其分配给某个值,可以是Path=.Path=OtherProperty

3
那是一个打错字,现在已经被修正了。 - Fueled
但是双向绑定仍然失败。它拒绝保存更改。如果您有一个 ObsColl<int> 并执行 Path=. Mode=TwoWay 绑定,添加到集合中就可以正常工作。例如,更改索引 0 处的数字不起作用。如果您将 datagrid 绑定到它并指定 datagridtextcolumn,则它会拒绝使用 Path=. 保存。 - user99999991

8
简而言之,两者的区别类似于传统的按值传递和按引用传递的区别。(参考 - 什么是按引用传递和按值传递的区别?
然而,我不明白为什么仅使用{Binding}不能用(它会引发“双向绑定需要路径或XPath”异常)。
现在暂时假设{Binding}可以用于双向绑定。一般来说,{Binding}创建一个基于数据上下文的值链接,不允许更新数据上下文。
{Binding Path=.}则是创建基于引用的链接,引用了'Path'指向的内存区域,从而允许通过引用更新值。(在这种情况下,“点”表示当前数据上下文)
希望这有所帮助!

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Jack Frost

7

这两者不同。如果您将其绑定到一个ObservableCollection的字符串类型的ConsoleMessages,只使用{Binding}会导致"双向绑定需要Path或XPath"异常,而{Binding Path=.}则可以正常工作。这是在WPF 4.0中的情况...

    <ItemsControl x:Name="ConsoleOutput" ItemsSource="{Binding ConsoleMessages, Mode=OneWay}" MaxHeight="400">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Path=.}" BorderThickness="0" Margin="0" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

我的个人看法...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接