绑定到内部属性?

18

我正在尝试使用MVVM来尝试一些不同的事情。我们ViewModel中绑定到View的属性是公共的。我以按钮绑定为例进行说明。以下是一个简单的示例。

View.xaml:

<Button Content="Test Button" Command="{Binding TestButtonCommand}" />

ViewModel.cs

private ICommand _testButtonCommand;
public ICommand TestButtonCommand
{
    get { return _testButtonCommand?? (_testButtonCommand= new RelayCommand(SomeMethod)); }
}

我的问题是:我们能否将TestButtonCommand设置为 internal 而不是 public?internal 表示它对当前项目是可访问的,因此这样做应该没有任何问题。但是当我尝试这样做时,它没有起作用。在 getter 中添加断点也没有命中。那么为什么我们不能将其设置为 internal?

以下是来自 MSDN 的链接:

http://msdn.microsoft.com/en-us/library/ms743643.aspx

您用作绑定源属性的属性必须是类的公共属性。显式定义的接口属性不能用于绑定目的,也不能使用没有基本实现的受保护、私有、内部或虚拟属性。

为什么我们不能这样做?

在访问同一项目的情况下,使用 internal 与 public 相同。那么为什么我们不能在这里使用 internal?这些属性必须是公共的,一定有原因,我正在寻找这个原因。

internal ICommand TestButtonCommand { ...... }

5
因为你只能绑定到公共属性、子属性和索引器或任何CLR对象。WPF团队为什么要做出这样的设计决策?我不知道,你应该去问他们 :) - Patryk Ćwiek
这是微软的事情,我们无能为力。 - fhnaseer
7个回答

26
如果在同一项目中,访问内部和公共访问是相同的。那么为什么我们不能在此处使用 internal 关键字呢?这些属性必须是公共属性才能用作绑定源的属性。推测原因可能是,internal 属性只能在同一程序集中访问,无法从外部访问。绑定到 internal 属性不起作用,因为绑定由 WPF 绑定引擎解析,该引擎位于 PresentationFramework.dll 程序集中。

2
那么,如何将绑定到视图模型类本身是内部的呢? - n.podbielski
2
这在Winforms中真的让我疯了。显而易见,但同时又不是那么简单。谢谢。 - Joel Etherton
我认为这并没有表述得很清楚,但我相信答案是正确的。属性不是公共的这一事实意味着绑定引擎本身无法访问它们,因此需要公共属性才能使其正常工作。 - StayOnTarget
@UuDdLrLrSs:我不理解提出的原因。绑定引擎难道不是将目标属性名称作为字符串获取吗?对于在运行时创建的“Binding”对象,这肯定是至少要做到的。从该字符串中,它只能通过使用反射之类的机制来查找实际属性。但是一旦使用了反射,无论属性是公共的、内部的还是其他任何东西,都不再重要——甚至可以通过反射找到和访问私有成员。您能详细说明一下为什么您认为这种推理是正确的吗?也许我漏掉了什么? - O. R. Mapper
@O.R.Mapper,看起来这不是.NET或反射本身的限制,所以我认为这是WPF中绑定的有意限制。我不知道微软这样做的理由是什么。它可能是技术上的限制,也可能是其他原因。我可以推测,如果内部属性在所有情况下都无法工作,他们可能会选择公共属性以保持一致性。 - StayOnTarget

12

绑定仅支持公共属性。MSDN参考文献:

http://msdn.microsoft.com/en-us/library/ms743643.aspx

引用文献中的内容如下

用作绑定源属性的属性必须是类的公共属性。不能访问显式定义的接口属性,也不能访问受保护、私有、内部或没有基本实现的虚拟属性。


2
我在尝试找出的原因是为什么我们不能使用internal。如果我们在同一个项目中工作,它与public相同。 - fhnaseer

2
显然,这取决于你想从这种情况中实现什么目标 - 你没有说明总体目标是什么。我刚刚遇到了我的代码中类似的问题,并找到了解决方案。我的一个库包含具有各种属性的帮助器对象,但当它们在应用程序项目中使用时,我只想看到对我有用的属性 - 例如,我想隐藏Command属性。
我隐藏它们不让库的“用户”看到的解决方案是添加
<EditorBrowsable(EditorBrowsableState.Never)>

对于我来说,每个属性都具有很少或没有兴趣的属性。

希望这能帮助到某些人!


2

internal 可见性对编译器和IL验证器来说才有意义,因为它们知道成员访问的全部上下文;但是WPF绑定引擎不知道。它只知道属性上存在一个绑定,却不知道谁设置了这个属性。它可以在XAML中设置,也可以在运行时动态设置(严格来说,即使你在XAML中设置了它,它仍然是动态应用的)。

由于没有强制执行访问规则,允许绑定到 internal 属性将等同于允许绑定到 private 属性,而不是 public 属性。


1

来自 http://msdn.microsoft.com/zh-cn/library/ms743643.aspx

对于CLR属性,只要绑定引擎能够使用反射访问绑定源属性,数据绑定就可以正常工作。否则,绑定引擎会发出警告,说明找不到该属性,并使用后备值或默认值(如果有)。


0
创建内部属性会破坏良好的OO设计和破坏封装性。您可以为您的情况使用内部set访问器(和public get访问器)。
public ICommand SaveCommand
{
    get;
    internal set;
}

如果您将一个字段封装到属性中,那么最好的做法是即使在类内部也始终通过属性访问该字段。

0

无法绑定内部属性。但是,如果您不希望类在项目外可访问,则可以将其设置为internal。


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