从 XAML 调用参数化构造函数

在使用 WPF 时,我注意到当我向一个 XAML 文件添加一个控件时,缺省构造函数被调用。

有调用参数化构造函数的方法吗?

45651 次浏览

不,不是从 XAML [使用 WPF 时]。

NET 4.0带来了一个新的特性,挑战了这个问题的答案——但显然只适用于 UWP 应用程序(而不是 WPF)。

X: 参数指令

<object ...>
<x:Arguments>
oneOrMoreObjectElements
</x:Arguments>
</object>

XAML 友好对象的指导原则之一是,它们应该完全可用于缺省构造函数,也就是说,不存在只有在使用非默认构造函数时才能访问的行为。为了适应 XAML 的声明性,通过属性设置器指定对象参数。还有一个约定是,在 XAML 中设置属性的顺序不应该很重要。

然而,你可能有一些特殊的考虑,这些考虑对你的执行很重要,但与惯例不符:

  1. 在使用对象之前,可以设置一个或多个 必须的属性。
  2. 两个或多个属性可能相互排斥,例如,同时设置图像的 StreamSourceUriSource是没有意义的。
  3. 您可能希望确保在初始化期间将属性设置为 只有
  4. 一个属性可能依赖于另一个属性,由于前面提到的在设置属性时顺序独立的约定,这可能比较棘手。

为了更容易处理这些情况,提供了 ISupportInitialize接口。当从 XAML 读取和创建对象(即,解析)时,将专门处理实现 ISupportInitialize的对象:

  1. 缺省构造函数会被召集。
  2. 将调用 BeginInit()
  3. 属性将按照它们在 XAML 声明中出现的顺序进行设置。
  4. EndInit()被称为。

通过跟踪对 BeginInit()EndInit()的调用,您可以处理需要强加的任何规则,包括设置某些属性的要求。这就是您应该如何处理创建参数; 而不是通过要求构造函数参数。

注意,还提供了 ISupportInitializeNotification,它通过添加 IsInitialized属性和 Initialized事件扩展了上面的接口。我建议使用扩展版本。

是的,你可以通过 ObjectDataProvider来实现。它允许你调用非默认的构造函数,例如:

<Grid>
<Grid.Resources>
<ObjectDataProvider x:Key="myDataSource"
ObjectType="{x:Type local:Person}">
<ObjectDataProvider.ConstructorParameters>
<system:String>Joe</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</Grid.Resources>
<Label Content="{Binding Source={StaticResource myDataSource}, Path=Name}"></Label>
</Grid>

假设 Person 是

public class Person
{
public Person(string Name)
{
this.Name = Name;
}
public string Name { get; set; }
}

遗憾的是,您无法绑定 ConstructorParameters