wpf 从 XAML 调用参数化构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1083159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:40:35  来源:igfitidea点击:

Calling a parameterized constructor from XAML

wpfxaml

提问by Hani

While using WPF I noticed that when I add a control to a XAML file, the default constructor is called.

在使用 WPF 时,我注意到当我向 XAML 文件添加控件时,会调用默认构造函数。

Is there a way to call a parameterized constructor?

有没有办法调用参数化构造函数?

回答by Raskal

.NET 4.0 brings a new feature that challenges the answer - but apparently only for UWP applications (not WPF).

.NET 4.0 带来了一项挑战答案的新功能 - 但显然仅适用于 UWP 应用程序(而非 WPF)。

x:Arguments Directive

x:参数指令

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

回答by Mike Strobel

One of the guiding principles of XAML-friendly objects is that they should be completely usable with a default constructor, i.e., there is no behavior that is only accessible when using a non-default constructor. To fit with the declarative nature of XAML, object parameters are specified via property setters. There is also a convention that says that the order in which properties are set in XAML should not be important.

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

You may, however, have some special considerations that are important to your implementation but at odds with convention:

但是,您可能有一些对您的实现很重要但与惯例不一致的特殊注意事项:

  1. You may have one or more properties which mustbe set before the object can be used.
  2. Two or more properties may be mutually exclusive with each other, e.g., it makes no sense to set both the StreamSourceand UriSourceof an image.
  3. You may want to ensure that a property is onlyset during initialization.
  4. One property may depend on another, which can be tricky due to the aforementioned convention of order independence when setting properties.
  1. 您可能有一个或多个必须在使用对象之前设置的属性。
  2. 两个或多个属性可能相互排斥,例如,设置图像的StreamSourceUriSource是没有意义的。
  3. 您可能希望确保在初始化期间设置属性。
  4. 一个属性可能依赖于另一个属性,由于在设置属性时前面提到的顺序无关约定,这可能会很棘手。

To make it easier to handle these cases, the ISupportInitializeinterface is provided. When an object is read and created from XAML (i.e., parsed), objects implementing ISupportInitializewill be handled specially:

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

  1. The default constructor will be called.
  2. BeginInit()will be called.
  3. Properties will be set in the order they appeared in the XAML declaration.
  4. EndInit()is called.
  1. 将调用默认构造函数。
  2. BeginInit()将被调用。
  3. 属性将按照它们在 XAML 声明中出现的顺序进行设置。
  4. EndInit()叫做。

By tracking calls to BeginInit()and EndInit(), you can handle whatever rules you need to impose, including the requirement that certain properties be set. This is how you should handle creation parameters; not by requiring constructor arguments.

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

Note that ISupportInitializeNotificationis also provided, which extends the above interface by adding an IsInitializedproperty and Initializedevent. I recommend using the extended version.

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

回答by Alun Harford

No. Not from XAML [when using WPF].

不。不是来自 XAML [使用 WPF 时]。

回答by chviLadislav

Yes, you can do it by the ObjectDataProvider. It allows you to call non default constructor, for example:

是的,您可以通过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>

assuming that Person is

假设 Person 是

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

Unfortunately you cannot bind the ConstructorParameters. See some workaround here.

不幸的是,您无法绑定ConstructorParameters. 在此处查看一些解决方法。