280 likes | 385 Views
Module 11 Control Customization. Module Overview. Overview of Control Authoring Creating Controls Managing Control Appearance by Using Visual States Integrating WPF and Windows Forms Technologies. Lesson 1: Overview of Control Authoring. Why Create New Controls?
E N D
Module 11 Control Customization
Module Overview • Overview of Control Authoring • Creating Controls • Managing Control Appearance by Using Visual States • Integrating WPF and Windows Forms Technologies
Lesson 1: Overview of Control Authoring • Why Create New Controls? • Options for Creating New Controls • Implementing User Controls • Implementing Custom Controls • Deriving from the FrameworkElement Class
Why Create New Controls? WPF provides many features that reduce the need to create new controls: • Rich content • Styles • Control templates • Triggers • Data templates
Options for Creating New Controls WPF provides three control-authoring models: • Deriving from the UserControl class • Deriving from the Control class • Deriving from the FrameworkElement class UserControl Control FrameworkElement
Implementing User Controls To create a user control: • Define a UserControl element by using XAML • Define a class that inherits from the UserControl class • Use styles and triggers if required You may want to create a user control when: • You want to build a control in a similar manner to how you build an application • Your control consists only of existing components • You do not need to support complex customization
Implementing Custom Controls To create a custom control: • Define a class that inherits from the Control class • Define a ControlTemplate element • Use themes if required You may want to create a custom control when: • You want to enable customization of your control by using control templates • You want your control to support various themes
Deriving from the FrameworkElement Class There are two method to create a control that derives from the FrameworkElement class: • Direct rendering • Custom element composition You may want to create a FrameworkElement-derived control when: • You want precise control over appearance • You want to use your own rendering logic • You want to use custom element composition
Lesson 2: Creating Controls • Creating a User Control • Implementing Properties and Events • Creating a Custom Control • Implementing Commands • Enhancing Controls by Using Themes • Demonstration: Implementing a NumericUpDown Control
Creating a User Control To create a user control: Create a UserControl XAML element Add layout elements and standard controls Implement a class that inherits from the UserControl class <UserControl x:Class="MyNamespace.NumericUpDown" ...> <Grid ...> <TextBlock .../> <RepeatButton ...>Up</RepeatButton> namespace MyNamespace { public class NumericUpDown : UserControl { ...
Implementing Properties and Events To define properties and events for a user control: • Define properties as dependency properties • Define events as routed events public static readonlyDependencyPropertyValueProperty = DependencyProperty.Register("Value", ...); public decimal Value { get { return (decimal)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonlyRoutedEventValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", ...);
Creating a Custom Control To define a custom control: • Create a class that inherits from the Control class • Define the appearance by using a Style element namespace MyNamespace { public class NumericUpDown : Control {...} ... <Application xmlns:local="clr-namespace:MyNamespace" ...> <Application.Resources> ... <ControlTemplate TargetType="{x:Type local:NumericUpDown}"> <Grid> ...
Implementing Commands You implement commands in custom controls to decouple the event handling for the control public class NumericUpDown : Control { public static RoutedCommandIncreaseCommand; public static RoutedCommandDecreaseCommand; ... Defined in the template of a Style element <RepeatButton Command="{x:Static local:NumericUpDown.IncreaseCommand}" ...>Up</RepeatButton> <RepeatButton Command="{x:Static local:NumericUpDown.DecreaseCommand}" ...>Down</RepeatButton>
Enhancing Controls by Using Themes To create a theme file: Create a folder named themes Create generic.xaml in the themes folder Define a ResourceDictionary with the Style element Specify the theme location in the hosting application Defined in generic.xaml <ResourceDictionary ...> <Style TargetType="{x:Type local:NumericUpDown}"> <ControlTemplateTargetType="{x:Type ...}"> ... In the hosting application [assembly: ThemeInfo( ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Demonstration: Implementing a NumericUpDown Control In this demonstration, you will see how to: • View the code for a user control implementation of the NumericUpDown control • View the code for a custom control implementation of the NumericUpDown control
Lesson 3: Managing Control Appearance by Using Visual States • Understanding the VisualStateManager Class • Implementing Visual States for Controls • Changing the Current Visual State • Demonstration: Implementing Visual States by Using the VisualStateManager Class
Understanding the VisualStateManager Class VisualStateManager.VisualStateGroups VisualStateGroup VisualState VisualState VisualState Contains a Storyboard element VisualStateGroup.Transitions VisualTransition VisualState VisualState Control Code: [TemplateVisualState( Name = "Normal", GroupName = "CommonStates")]
Implementing Visual States for Controls <VisualStateManager.VisualStateGroups> <VisualStateGroup Name="CommonStates"> <VisualState Name="Normal" /> <VisualState Name="MouseOver"> <Storyboard> <ColorAnimation To="Green" Storyboard.TargetName="rectBrush" Storyboard.TargetProperty="Color"/> </Storyboard> </VisualState> <VisualStateGroup.Transitions> <VisualTransition To="Normal" GeneratedDuration="00:00:00"/> <VisualTransition To="MouseOver" GeneratedDuration="00:00:00.5"> <VisualTransition.GeneratedEasingFunction> <ExponentialEaseEasingMode="EaseOut" Exponent="10"/> </VisualTransition.GeneratedEasingFunction> </VisualTransition> </VisualStateGroup.Transitions> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
Changing the Current Visual State Default transition Control Code: VisualStateManager.GoToState(this, "MouseOver", true);
Demonstration: Implementing Visual States by Using the VisualStateManager Class In this demonstration, you will see how to: • Open the existing application • View the control template • View the visual states • View the visual state transitions • View the NumericUpDown control code • Run the application
Lesson 4: Integrating WPF and Windows Forms Technologies • Understanding WPF and Windows Forms Integration • Hosting Windows Forms Controls in a WPF Application • Hosting WPF Controls in a Windows Forms Application
Understanding WPF and Windows Forms Integration Windows Forms integration: • Reuse existing investment in Windows Forms code • Some Windows Forms controls have no WPF equivalent WPF integration: • Enhance existing investment in Windows Forms code • Enables iterative approach to migration to WPF
Hosting Windows Forms Controls in a WPF Application System.Windows.Forms and WindowsFormsIntegration assemblies WindowsFormsHost element <Window ... > ... <WindowsFormsHost x:Name="wfh"> <wf:MaskedTextBox x:Name="mtb" Mask="00/00/000" /> </WindowsFormsHost> ... </Window> • Child property • Cast to relevant type • Attach event handlers • Manipulate properties (this.wfh.Child as MaskedTextBox).ValueChanged += new EventHandler(this.MaskedTextBox_ValueChanged);
Hosting WPF Controls in a Windows Forms Application WindowsFormsIntegration assembly private void MyForm_Load(object sender, EventArgs e) { elemHost = new ElementHost(); ... System.Windows.Controls.ButtonwpfButton = new System.Windows.Controls.Button(); wpfButton.Content = "Windows Presentation Foundation Button"; elemHost.Child = wpfButton; // Map the Margin property. this.AddMarginMapping(); // Remove the mapping for the Cursor property. this.RemoveCursorMapping(); // Cause the OnMarginChange delegate to be called. elemHost.Margin = new Padding(23, 23, 23, 23); }
Lab: Building a User Control • Exercise 1: Choosing the Appropriate Control Type • Exercise 2: Creating a WPF User Control • Exercise 3: Adding a WPF Control to a Windows Forms Application Logon information Estimated time: 45 minutes
Lab Scenario You have been asked to turn your prototype graphic control into a control that the Product Inventory application will consume. The Product Inventory application is written by using Windows Forms, but you will use WPF to write the new control; therefore, you must also integrate the new control into the older application.
Lab Review Review Questions • Which method do you use to create a dependency property? • Which control do you use to host a WPF control in a Windows Forms application? • Which property do you use to add or remove property mappings for a hosted control?
Module Review and Takeaways • Review Questions • Best Practices