假设我想创建一个专门的wpf控件,“YellowTextBox”。它将是一个普通的TextBox,但它将是......黄色!好的,我去代码:
public class YellowTextBox: TextBox
{
}
现在,显而易见的部分,我希望它是黄色的......
this.Background = Brushes.Yellow;
我把那行代码放在哪里?在构造函数中?在OnInitialized覆盖? OnLoaded等...
有一些正确的(或更好的)放置那行代码的地方?
编辑:
我知道我可以通过样式来做,我的问题更像是一种“OOP”方式,它可以是任何其他类型的属性或字段,而不是完全背景颜色,所选属性只是一个例子:/
答案 0 :(得分:6)
你真的应该在依赖项属性的初始值设定项中初始化一个专用的WPF控件(对于它引入的属性),并在默认的Style
中(对于新属性,以及它继承的任何需要不同的属性)默认值)。
但是你想用C#做这件事,出于某种原因。也许Darth Vader站在你身后,喘着粗气,威胁如果你触摸XAML文件就会扼杀你的生命。这不太可能,但在湾区发生了很多有趣的事情。无论好坏,这都是你提出的问题。
在这种情况下,我们谈论的是a)OOP神学,b)OOP现实,以及C)WPF技巧。就所有而言,在构造函数中执行,在WPF中,在InitializeComponent()
之后的构造函数中执行(如果适用,不是在您的情况下)。在WPF中应用于控件的任何样式之前,它都是优秀的OOP练习和神学来初始化你没有初始化的构造函数中的所有内容字段初始化程序。 一个类的新实例应该全部闪亮并且准备就绪,处于一致状态,如果你开始使用它就不会抛出任何异常或做任何事情。这意味着初始化应该在那一点完成(因此名称;没有人称之为"有些程度化")。从不,永远,永远不会给任何人留下任何初始化。没有必要,这对你的代码消费者来说是一个破旧的伎俩。让人们想到你的内心。 "不要写Booby Traps"几乎同样重要的格言和#34;保持简单"。也许它是相同的格言。
请阅读InitializeComponent()
,但在您的特定情况下,标准控件的子类的构造函数,您将无法调用它。
WPF中的控件子类将在构造函数之后应用样式。它必须!在构造函数执行之前,它不存在。 "在构造函数之后"除了构造函数本身的内容之外,它基本上都是存在的。在应用模板后,您可以覆盖OnApplyTemplate()
以立即挂钩。但是,初始化的时间已经太晚了(除了涉及模板子项的私有字段之外 - 在模板应用之前,它们无法初始化,因为控件不会被覆盖。存在)。例如,假设存在"PART_FooBar"
,您可以将事件处理程序与"PART_FooBar"
或模板中的任何内容联系起来。
因此,如果您在构造函数中初始化东西,它将应用于每个实例,如果它是WPF控件类(或任何FrameworkElement
子类),您的类的使用者可以覆盖它稍后应用Style
或模板。这是一个很好的WPF练习:您希望允许人们以最大的方式自定义您的控件。
顺便说一句,在C#中你可以链接构造函数:
// Assume that Whoop declares Bar and initializes it in its constructor
class Foo : Whoop {
public Foo(int bar = 0) : base(bar) {}
public Foo(int bar, string baz) : this(bar) { Baz = baz; }
// C#6
public String Baz { get; set; } = "yabba dabba do";
}
如果你有一堆不同的构造函数参数,加上初始化对所有这些参数都很常见但不能放在字段/属性初始值设定项中,这很方便。