Code-Behind and Partial Classes
Code-behind is a term used to describe the code that is joined with the XAML page's partial class when markup-compiled for an application. This topic describes requirements for code-behind classes, requirements for event handlers defined in code-behind, and the purpose of mechanisms related to code-behind, such as the InitializeComponent method.
This topic contains the following sections.
- General Requirements
- Code-behind and Partial Class Requirements
- Event Handler Requirements
- Partial Class Features
- Related Topics
- If a XAML page for a managed application is markup-compiled (Page build action, with Custom Tool value of MSBuild:MarkupCompilePass1) the root element on the page should declare an x:Class. As a fallback, there can be the code-behind file only (a DependentUpon file with build action Compile); see note in next section.
Code-behind and Partial Class Requirements
The partial class must derive from the type of the class that was used as the root element.
Although not recommended, you can leave the derivation blank in the partial class definition in code-behind so long as the markup declared x:Class. You would do so only if your page had no event handlers at all, or other code-based logic. The compiled result will assume the page root to be the base class for the partial class even if it not specified (because the markup half of the partial class does specify the base class implicitly through its root element tag).
The partial class must be public. This is required because the partial class defined through the markup x:Class is public when markup-compiled, so the code partial class must use the same access in order to be joined with the markup's partial class.
You can choose to omit a namespace, so long as this matches how you declared your x:Class.
Event Handler Requirements
The event handlers you write must be instance methods defined by the partial class within the namespace identified by x:Class. You cannot qualify the name of an event handler to instruct a XAML processor to look for that handler in a different class scope. You also cannot use a static method as an event handler.
The event handlers do not need to be public; they can be private or internal. Writing non-public event handlers is generally recommended.
The handler must match the delegate for the appropriate event. Note that some events use generic handlers with constrained event data. In these cases, use the constraint on event data that is indicated in the event signature.
You can share event handlers for the same event on different objects. If permitted by the delegate, you can also share the same handler for different event types. However, if you do this, your event handler logic should use the values of sender and/or OriginalSource to distinguish event sources.
For the Visual Basic language specifically, you can use the language-specific Handles keyword to associate handlers with instances and events in the handler declaration, instead of attaching handlers with attributes in XAML. However, this technique does have some limitations because Handles cannot support all of the specific features of the event system, such as certain routed event scenarios.
Partial Class Features
If you examine the partial class that is created from the Silverlight project templates, you will see that it starts with template-created code that has a constructor calling the InitializeComponent method. You do not typically write InitializeComponent yourself. InitializeComponent is code-generated by the Silverlight targets when the page associated with the code-behind is markup-compiled. You can examine the code-generated InitializeComponent by looking in the obj folder of your project after a successful compile. Look for a file that has .g. in its name, with .g. interjected between the name and extension of the filename of your code-behind file. Open this file and look at the InitializeComponent definition.
The main purpose of InitializeComponent is to connect fields that hold references to each of the objects that are created by markup-compiling the XAML. These fields enable the code in the code-behind to make run-time references to any object where you provide a Name / x:Name attribute in the object element that defines the object in XAML. Without the ability to retrieve objects by name, you would have to walk the Silverlight object tree from entry points such as sender from event handlers or the RootVisual to find specific objects.
InitializeComponent also initializes the render for the Silverlight content area when the class is used as the RootVisual.
In the managed API, it is the Application object that controls what is displayed in the Silverlight content area, and to do so it must be able to set its RootVisual to an instance of a UIElement class. Therefore you typically need to declare x:Class on any XAML page root you intend to load as content for a managed Silverlight-based application, so that RootVisual can reference the class, even if there is no code-behind in that page.