假设我要创建一个专门的wpf控件,"YellowTextBox".它将是一个普通的TextBox,但它将是......黄色!好的,我去代码:
public class YellowTextBox: TextBox
{
}
Run Code Online (Sandbox Code Playgroud)
现在,显而易见的部分,我希望它是黄色的......
this.Background = Brushes.Yellow;
Run Code Online (Sandbox Code Playgroud)
我把那行代码放在哪里?在构造函数中?在OnInitialized覆盖?OnLoaded等...
有一些正确的(或更好的)放置那行代码的地方?
编辑:
我知道我可以通过样式来做,我的问题更像是一种"OOP"方式,它可以是任何其他类型的属性或字段,而不是完全背景颜色,所选属性只是一个例子:/
您真的应该在依赖项属性(对于它引入的属性)的初始化程序中初始化专用WPF控件,并在默认情况下Style(对于新属性,以及它继承的需要不同默认值的任何内容).
但是出于某种原因,你想在C#中做到这一点.也许Darth Vader站在你身后,喘着粗气,威胁如果你触摸XAML文件就会扼杀你的生命.这不太可能,但湾区发生了很多有趣的事情.无论好坏,这都是你要问的问题.
在这种情况下,我们谈论的是a)OOP神学,b)OOP现实,以及C)WPF机制.就所有这些而言,在构造函数中执行它,并在WPF中,在构造函数之后InitializeComponent()(如果适用,不在您的情况下)调用它.这将在任何应用于WPF中的控件的样式之前,并且在初始化构造函数中未在字段初始化程序中初始化的所有内容中都是很好的OOP实践和神学.一个新的类实例应该全部闪亮并且准备就绪,处于一致状态,如果你开始使用它就不会抛出任何异常或做任何事情.这意味着初始化应该在那一点完成(因此名称;没有人称之为"somelaterization").从不,永远,永远不会给任何人留下任何初始化.没有必要,这对你的代码消费者来说是一个简单的伎俩.让人们想到你的内心."不写鲣鸟"几乎和"保持简单"一样重要.也许这是同样的格言.
请阅读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";
}
Run Code Online (Sandbox Code Playgroud)
如果你有一堆不同的构造函数参数,以及所有这些参数的公共初始化但是不能放在字段/属性初始值设定项中的初始化,这很方便.