Module 6 Simple Data Binding and Validation Module Overview • Overview of Data Binding • Creating a Data Binding • Implementing Property Change Notification • Converting Data • Validating Data • Presenting Data at Design Time Lesson 1: Overview of Data Binding • The WPF Data-Binding Model • Binding Sources and Binding Targets • Data-Binding Modes The WPF Data-Binding Model Managed Object ADO.NET Data Source XML Data Dynamic Object UI Element Binding Sources and Binding Targets Data-binding components: • Binding target object • Binding target dependency property • Binding source • Path to the binding source property Binding target object Binding source object Dependency property Property Data-Binding Modes WPF supports four data-binding modes: • OneWay • OneWayToSource • TwoWay • OneTime Binding object OneWay TwoWay OneWayToSource OneTime Binding target Binding source Lesson 2: Creating a Data Binding • Binding to a Class Property • Binding Multiple Controls to a Class • Binding to a Full Object • Binding to XML Data • Binding to User Interface Controls • Demonstration: Binding to Different Data Sources Binding to a Class Property To bind a control property to a class property: • Define a resource that specifies the binding source class • Specify the class property for binding in the path <DockPanel xmlns:c="clr-namespace:MyNamespace"> <DockPanel.Resources> <c:MyClass x:Key="mySource" /> </DockPanel.Resources> Path <Button Background= "{Binding Path=ColorName, Source={StaticResource mySource}}"> ... </Button> Source </DockPanel> Binding Multiple Controls to a Class To bind multiple controls to class properties: • Set the DataContext property for a parent element • Bind controls to the class properties <DockPanel xmlns:c="clr-namespace:MyNamespace"> <DockPanel.Resources>...</DockPanel.Resources> <DockPanel.DataContext> Source <Binding Source="{StaticResource mySource}"/> </DockPanel.DataContext> <Button Background="{Binding Path=BackColorName}"> ... </Button> <TextBox Foreground="{Binding Path=ForeColorName}"> ... </TextBox> Path Path </DockPanel> Binding to a Full Object To bind to a full object: • Omit the Path property in the Binding object • Use the empty binding syntax if the source is inherited <DockPanel xmlns:sys="clr-namespace:System;assembly=mscorlib"> <DockPanel.Resources> <sys:String x:Key="myData">Hello World!</sys:String> </DockPanel.Resources> <DockPanel.DataContext> Source <Binding Source="{StaticResource myData}"/> </DockPanel.DataContext> <Label Content="{Binding}"> </DockPanel> Empty binding syntax Binding to XML Data To bind to a XML data: • Use the XPath property in the Binding object • Use the Path property to bind to the node properties <ListBox> Source <ListBox.ItemsSource> <Binding Source="{StaticResource inventoryData}" XPath="*[@Stock='out'] | *[@Number>=8 or @Number=3]"/> </ListBox.ItemsSource> XPath query ... <TextBlock Text="{Binding XPath=Title}"> <TextBlock.Tooltip> <TextBlock Text="{Binding Path=Attributes[0].Value}" /> </TextxBlock.Tooltip> </TextBlock> Node binding ... </ListBox> Binding to User Interface Controls To bind to a UI control: Use the ElementName property in the Binding object Source element <StackPanel> <ComboBox x:Name="myComboBox" SelectedIndex="0"> ... </ComboBox> <Canvas Background="{Binding ElementName=myComboBox, Path=SelectedItem.Content}" Height="100" Width="100" /> Path </StackPanel> ElementName Demonstration: Binding to Different Data Sources In this demonstration, you will see how to: • Bind to a class property • Bind multiple controls to a class • Bind to a full object • Bind to XML data • Bind to another UI element Lesson 3: Implementing Property Change Notification • Understanding Property Change Notifications • Propagating Property Change Notifications to a Binding Target • Propagating Value Changes to a Binding Source • Demonstration: Triggering Source Updates Understanding Property Change Notifications Bindings listen for changes in the target property and propagate them back to the source The time when the update happens is defined by the UpdateSourceTrigger property Binding object Binding target OneWay TwoWay OneWayToSource UpdateSourceTrigger Binding source Propagating Property Change Notifications to a Binding Target Use dependency properties for visual elements To implement the INotifyPropertyChanged interface: • Declare the PropertyChanged event • Create the OnPropertyChanged method • Call the OnPropertyChanged method public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; } // Raise the PropertyChanged event // when property values in the class change. Propagating Value Changes to a Binding Source Specify the timing of binding source updates by using the UpdateSourceTrigger property • Default • Explicit • LostFocus • PropertyChanged <TextBox Width="100"> <TextBox.Text> <Binding Source="{StaticResource myData}" Path="ColorName" UpdateSourceTrigger="PropertyChanged" /> </TextBox.Text> </TextBox> Demonstration: Triggering Source Updates In this demonstration, you will see how to: • Propagate changes to the binding target • Propagate value changes to a binding source Lesson 4: Converting Data • Default Data Conversions • Implementing a Custom Value Converter Default Data Conversions The data type of the binding source property must be compatible with the binding target property • WPF performs default data type conversion, if possible • An error occurs if no default conversion is possible Binding target Button object Background property (of type Brush) Binding source Default conversion MyData object ColorName property (of type String) Implementing a Custom Value Converter To implement a custom value converter class: • Define a class that implements the IValueConverter interface • Annotate the class with the ValueConversion attribute • Implement the Convert and ConvertBack methods Background property (of type Brush) ColorBrushConverter ColorName property (of type String) Lesson 5: Validating Data • Default Data Validation • Providing Visual Validation Feedback • Defining a Custom Validation Rule • Specifying Validation Rules by Using XAML • Implementing Validation of Business Rules Default Data Validation WPF applications can validate user input • Associate validation rules with a Binding object • Test the type, range, or format of user input Binding Source Binding target Dependency property Validation Converter <Binding.ValidationRules> <ExceptionValidationRule /> </Binding.ValidationRules> Property Providing Visual Validation Feedback You can provide visual feedback by using a validation template • Define a ControlTemplate for the validation template • Set the control location by using the AdornedElementPlaceholder control • Apply validation rule by setting the Validation.ErrorTemplate property <ControlTemplate x:Key="errorTemplate"> <DockPanel> <TextBlock Foreground="Red">!</TextBlock> <AdornedElementPlaceholder/> </DockPanel> </ControlTemplate> <TextBox Validation.ErrorTemplate = "{StaticResource errorTemplate}" ...> Defining a Custom Validation Rule To implement a custom validation rule: 1. Define a class that derives from the ValidationRule class 2. Implement the Validate method public class FutureDateRule : ValidationRule { public override ValidationResult Validate( object value, CultureInfo ci) { ... } } Specifying Validation Rules by Using XAML To use a custom validation rule in XAML: • Set the ValidationRules property for a Binding object • Specify the name of the custom validation class <TextBox xmlns:src="clr-namespace:MySample"> <TextBox.Text> ValidationRules <Binding ...> <Binding.ValidationRules> <src:FutureDateRule /> </Binding.ValidationRules> </Binding> Custom validation </TextBox.Text> class </TextBox> Implementing Validation of Business Rules Steps to implement business object validation: 1. Define a class that implements the IDataErrorInfo interface 2. Configure the target binding by using either the ValidatesOnDataErrors attribute or the DataErrorValidationRule class public class Person : IDataErrorInfo { public string Error { get; } public string this[string name] { get { ... } } } <TextBox DataContext="{StaticResource APerson}" Text="{Binding Age, ValidatesOnDataErrors=True}" /> Lesson 6: Presenting Data at Design Time • Understanding Data at Design Time • Understanding Design-Time Attributes • Demonstration: Using Design-Time Attributes Understanding Data at Design Time Without data at design time: Controls do not look as they will at run time, making design choices for layout, font sizes and weights, colors, and gradients difficult Understanding Design-Time Attributes Steps to use design-time attributes: 1. Add the required XML namespaces to your XAML file 2. Add an Ignorable attribute 3. Use the properties in the design-time attributes Ignorable attribute <Window mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markupcompatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="350" Required XML d:DesignWidth="500" namespaces SizeToContent="WidthAndHeight"> ... </Window> Use of the attributes Demonstration: Using Design-Time Attributes In this demonstration, you will see how to: • Create sample data files • Use the DesignHeight, DesignWidth, DataContext, and DesignData attributes Lab: Data Binding • Exercise 1: Binding Controls • Exercise 2: Implementing Property Change Notifications • Exercise 3: Validating Data • Exercise 4: Implementing a Value Converter Logon information Virtual machine 10262A-GEN-DEV User name Student Password Pa$$w0rd Estimated time: 60 minutes Lab Scenario You have been asked to update the Work Orders application to enable the creation of new work orders. You must also ensure that the data is correctly validated at all points in the application. Lab Review Review Questions • What is the purpose of the IDataErrorInfo interface? • Which class should you inherit from to create a custom validation rule? Module Review and Takeaways • Review Questions • Best Practices