StylingA style is much like a class definition in CSS, it describes the appearance of an element and can be applied to all elements of the same type or via a resource name to a particular instance of a type. A style is also a set of properties applied to content used for visual rendering. A style can be used to set properties on an existing visual element, such as setting the font weight of a Button control, or it can be used to define the way an object looks, such as showing the name and age from a Person object. In addition to the features in word processing styles , WPF styles have specific features for building applications, including the ability to associate different visual effects based on user events, provide entirely new looks for existing controls, and even designate rendering behavior for non-visual objects. All of these features come without the need to build a custom control. The following example shows how a named style can be defined in a resource container and applied to instances. <stackpanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" <textbox Style="{StaticResource MyStyle}">TextBox 1</textbox> A style can also be defined inline as follows: <button Width="200" Content="Swa" Height="66"> One of the remarkable things with styles is that the set of dependency properties are applied if the element supports it. No exception is generated if you define a style property that the element cannot render. Styles can inherit from each other by means of the BasedOn attribute as shown in the following example: <page .Resources> <style x:Key="CellTextStyle"> </page> Finally, you can define a trigger in a style based on events, for example here a mouseover effect on a button <page .Resources> <style x:Key="CellTextStyle"> </style>
</page> Tadaa TemplatesTemplates extend styles by describing the visual structure of a control or data type; <controltemplate> The control author can define the default ControlTemplate and the application author can override the ControlTemplate to reconstruct the visual structure of the control. Control templating is one of the many features offered by the WPF styling and templating model. The styling and templating model provides you with such great flexibility that in many cases you do not need to write your own controls. A ControlTemplate is intended to be a self-contained unit of implementation detail that is invisible to outside users and objects, including styles. The only way to manipulate the content of the control template is from within the same control template. <stackpanel xmlns="http://schemas.microsoft.com/winfx/avalon/2005" <contentpresenter Margin="20,0,20,0" DerivationsYou can derive from Control, ContentControl, UserControl and FrameworkElement. ControlIf you add a custom control via a "New Item..." in Visual Sutdio 2005 you will get a control inheriting from Control and themed via the generic.xaml file under the theme directory. The constructor code shows something like this to enable themes: static CustomControl1() In the XAML code you can add your custom control via the usual aliasing tag. What is important to know here is that the generic style can be overriden in the application as follows; <window x:Class="FromFrameworkElement.Window1" <style TargetType="{x:Type local:CustomControl1}"> It means that you can define your custom control inside a separate assembly, define a default or generic style linked to some C# code and then hand it over to some consuming application. Inside the application you simply define your own style and all the code-behind is kept alive without problems. It really is like skinning an existing control. Wonderful uh? FrameworkElementIf you intend to use FrameworkElement as a base class, you might want to first examine the existing derived classes. FrameworkElement provides support for a number of basic scenarios, but also lacks a number of features that are desirable for an "element" in the sense of a building block that you use to create user interface (UI) in Extensible Application Markup Language (XAML). For instance, a FrameworkElement does not define any true content model; you cannot place a child element within a true FrameworkElement in Extensible Application Markup Language (XAML). In particular, you might want to look at Control and ContentControl. Inheriting from FrameworkElement also does not allow you (out of the box) to template the control as in the example above. It‘s not an easy task to give you guidance in choosing the right class to inherit from. I have found that you need to dig deep in the class hierarchy to see what is right and wrong. One place to start is the MSDN documentation on base clases. In most circumstance I reckon the ContentControl is a better choice than the FrameworkElement class. Along the ride you should have a look at the Microsoft.Windows.Themes namespace with the four predefined themes. One thing you should be surprised about is the fact that in overriding the OnRender method of the FrameworkElement we‘re back to the mediaval days of rendering controls, as I learned from Petzold‘s example; public class BetterEllipse : FrameworkElement // Public interfaces to dependency properties. if (Stroke != null) return sizeDesired; // Adjust rendering size for width of Pen. // Draw the ellipse. The FrameworkElementFactoryIf you want to template controls you better have a look at the factories inside the framework which help you build up the visual tree, here‘s an example: public BuildButtonFactory() // Create a ControlTemplate intended for a Button object. // Create a FrameworkElementFactory for the Border class. // Give it a name to refer to it later. // Set certain default properties. // Create a FrameworkElementFactory for the ContentPresenter class. // Give it a name to refer to it later. // Bind some ContentPresenter properties to Button properties. // Notice that the button‘s Padding is the content‘s Margin! // Make the ContentPresenter a child of the Border. // Make the Border the root element of the visual tree. // Define a new Trigger when IsMouseOver is true. // Associate a Setter with that Trigger to change the // Add the Setter to the Setters collection of the Trigger. // Similarly, define a Setter to change the FontStyle. // Add it to the same trigger‘s Setters collection as before. // Add the Trigger to the template. // Similarly, define a Trigger for IsPressed. set = new Setter(); // Add the Setter to the trigger‘s Setters collection. // Add the Trigger to the template. // Finally, create a Button. // Give it the template. // Define other properties normally. Content = btn; Routed CommandsCommands are related to events in the sense that it allows you to attach handlers to actions performed by the user in the UI layer. The whole mechanism of routed commands and dependency properties is rather involved and I hope to describe more in details later on the way I have used commands in XPad. For now I only want to record here the way you can bind command to UI elements in code: <button Command="ApplicationCommands.Help" private void HelpCmdExecuted(object sender, ExecutedRoutedEventArgs e) |
|