Click Ok Click Ok - 2 months ago 12
C# Question

Where initialize a specialized wpf control?

Let's say that I want create a specialized wpf control, "YellowTextBox". It will be the same of a common TextBox, but it will be... yellow!. Ok, I go to code:

public class YellowTextBox: TextBox

Now, the obvious part, I want it be yellow...

this.Background = Brushes.Yellow;

Where I put that line of code? In the constructor? In OnInitialized override? OnLoaded, etc...

There are some correct (or better) place to put that line of code?


I know I can do it via styles, my question is more an "OOP" way of do it, it can be any other kind of property or field, not exactly Background Color, that selected property was just an example :/


You really ought to initialize a specialized WPF control in the initializers for the dependency properties (for properties it introduces), and in the default Style (for the new properties, and for anything it inherits that needs a different default value).

But you want to do it in C#, for some reason. Maybe Darth Vader is standing behind you, breathing heavily, threatening to choke the life out of you if you touch a XAML file. This is unlikely, but a lot of funny things happen in the Bay Area. For good or ill, that's the question you're asking.

In that case, we're talking about a) OOP theology, b) OOP reality, and C) WPF mechanics. In terms of all of those, do it in the constructor, and in WPF, in the constructor after InitializeComponent() (if applicable, not in your case) is called. That'll precede any styles that get applied to the control in WPF, and it's good OOP practice and theology to initialize everything in the constructor that you didn't initialize in field initializers. A new instance of a class should be all shiny and ready to go, in a consistent state that won't throw any exceptions or do anything crazy if you start using it. So that means the initialization should be all complete at that point (hence the name; nobody calls it "somewhatlaterization"). Never, never, never leave any initialization to anybody else. There's no need and it's a shabby trick to play on consumers of your code. Spare people any thought of your internals. "Don't Write Booby Traps" is almost as important an aphorism as "Keep it Simple". Maybe it's the same aphorism.

Do read up on InitializeComponent(), but in your specific case, the constructor for a subclass of a standard control, you won't be calling it.

A control subclass in WPF will apply styles after the constructor. It must! Before the constructor executes, it doesn't exist. "After the constructor" is basically all there is, aside from the guts of the constructor itself. You can override OnApplyTemplate() to hook into things immediately after the template is applied. But that's much too late to be initializing much (with the sole exception of private fields which will refer to template children -- they can't be initialized until the template is applied, because the controls don't exist). That's when you'd, for example, hook up event handlers to "PART_FooBar" or whatever in the template, assuming "PART_FooBar" exists.

So if you initialize stuff in the constructor(s), it gets applied to every instance, and if it's a WPF control class (or any FrameworkElement subclass), consumers of your class can override it by applying a Style or a template later on. That's good WPF practice: You want to allow people maximum scope to customize your controls in ways that won't blow stuff up.

By the way, in C# you can chain constructors:

//  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";

This is handy if you've got a bunch of different sets of constructor parameters, plus initialization that's common to all of them but which can't be put in field/property initializers.