Monday, 29 July 2013

Notifying the user of validation errors using Prism for the Windows Runtime

Previously I’ve blogged about how to create a model class with validation support by using Prism for the Windows Runtime. This was achieved by deriving the model class from Prism’s ValidatableBindableBase class.

In this blog post I’ll demonstrate how to hook up the model class to code that will allow the user to input text, perform the validation, and notify the user of any validation errors in the input.

Implementation

The MainPageViewModel class creates an instance of the Person model class and allows its data to be validated.

public class MainPageViewModel : ViewModel
{
    private Person _person;
 
    public DelegateCommand ValidateCommand { get; private set; }
    public Person Person
    {
        get { return _person; }
        set { SetProperty(ref _person, value); }
    }
 
    public MainPageViewModel()
        : this(new Person())
    {
    }
 
    public MainPageViewModel(Person person)
    {
        _person = person;
        ValidateCommand = new DelegateCommand(Validate);
    }
 
    private void Validate()
    {
        _person.ValidateProperties();
    }
}

The TextBox on the MainPage binds to the instance of the Person model class through the Person property. This instance is created when the MainPageViewModel is constructed. The Button on the MainPage binds to the ValidateCommand. When the ValidateCommand is invoked the Validate method is called.

Triggering validation explicitly

I’ve previously explained how validation can be triggered automatically when property values change. In addition, validation can also be triggered explicitly by calling the ValidatableBindableBase.ValidateProperties method, which in turn calls the BindableValidator.ValidateProperties method. This is accomplished by the Validate method in the MainPageViewModel class. For an explanation of how the BindableValidator.ValidateProperties method works see Validating user input in AdventureWorks shopper.

Highlighting validation errors

In this sample app validation errors are shown to the user by highlighting the TextBox control that contains invalid data, and by displaying an error message beneath the control.

image

image

The HighlightOnErrors attached behaviour is used to highlight the TextBox control when a validation error occurs. The behaviour is attached to the TextBox control that is used for user input.

<TextBox behaviours:HighlightOnErrors.PropertyErrors="{Binding Person.Errors[Name]}"
         Grid.Column="1"
         Grid.Row="2"
         Text="{Binding Person.Name, Mode=TwoWay}" />

The attached behaviour gets and sets the PropertyErrors dependency property, which is defined in the HighlightOnErrors class.

public static DependencyProperty PropertyErrorsProperty =
    DependencyProperty.RegisterAttached("PropertyErrors", typeof(ReadOnlyCollection<string>), typeof(HighlightOnErrors),
    new PropertyMetadata(BindableValidator.EmptyErrorsCollection, OnPropertyErrorsChanged));

The PropertyErrors dependency property is registered as a ReadOnlyCollection of strings, by the RegisterAttached method. When the value of the PropertyErrors dependency property changes, the OnPropertyErrorsChanged method is invoked to change the highlighting style of the TextBox.

private static void OnPropertyErrorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
    if (args == null || args.NewValue == null)
    {
        return;
    }
 
    TextBox textBox = (TextBox)d;
    var propertyErrors = (ReadOnlyCollection<string>)args.NewValue;
    Style textBoxStyle = (propertyErrors.Count() > 0) ? (Style)Application.Current.Resources["HighlightTextStyle"] : null;
    textBox.Style = textBoxStyle;
}

The OnPropertyErrorsChanged method gets the instance of the TextBox that the PropertyErrors dependency property is attached to, and gets any validation errors for the TextBox. If validation errors are present the HighlightTextStyle is applied to the TextBox, so that it is highlighted with a red BorderBrush.

Finally, the UI displays the validation error message in a TextBlock below the TextBox control.

<TextBlock Grid.Column="1"
           Grid.Row="3"
           Style="{StaticResource ErrorMessageStyle}"
           Text="{Binding Person.Errors[Name], Converter={StaticResource FirstErrorConverter}}" />

The TextBlock binds to the Errors property of the Person object. The Errors property is provided by Prism’s ValidatableBindableBase class, and is an instance of the BindableValidator class. The indexer of the BindableValidator class returns a ReadOnlyCollection of error strings, with the FirstErrorConverter retrieving the first error from the collection, for display.

Summary

In this blog post I’ve demonstrated how to use Prism for the Windows Runtime to validate user input, and notify the user of any validation errors. The ValidatableBindableBase.ValidateProperties method performs validation, with the HighlightOnErrors attached behaviour highlighting the control that contains the validation error. Validation error text can be retrieved from the Errors property of the model object, which is provided by Prism’s ValidatableBindableBase class.

The sample app can be downloaded here.

Monday, 22 July 2013

Creating a model class with validation support using Prism for the Windows Runtime

The Windows Runtime has no in-built support for validation. Therefore in Prism for the Windows Runtime we added functionality to allow validation of user input and notification of validation errors back to the user. For more info see Validating user input in AdventureWorks Shopper.

In order to demonstrate the validation features of Prism I’ve decided to create a new small sample app. The app allows the user to enter their name, and then performs validation of the user input.

Implementation

The Microsoft.Practices.Prism.StoreApps library provides validation support to apps. In order to use Prism’s validation support your model classes must derive from the ValidatableBindableBase class. This class provides an error container whose contents are updated whenever a model class property value changes. The ValidatableBindableBase class derives from Prism’s BindableBase class, which raises property change notification events.

Specifying validation rules

Validation rules are specified by adding data annotation attributes that derive from the ValidationAttribute class to the declaration of the model property that you want to validate.

public class Person : ValidatableBindableBase
{
    private string _name;
 
    private const string RegexPattern = @"\A\p{L}+([\p{Zs}\-][\p{L}]+)*\z";
 
    [Required(ErrorMessage = "Name is required")]
    [RegularExpression(RegexPattern, ErrorMessage = "Name must contain only letters and spaces. Hypens are also allowed, but they cannot occur in sequences.")]
    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }
}

In the Person class the Name property contains a Required attribute which specifies that a validation failure will occur if the field is null, contains an empty string, or contains only white-space characters. The RegularExpression attribute specifies that the Name property must match the regular expression given by the RegexPattern constant. This regular expression allows user input to consist of all unicode name characters as well as spaces and hyphens, as long as the spaces and hyphens don’t occur in sequences and are not leading or trailing characters. Each validation attribute also specifies the error message that will be returned to the user if validation fails.

Triggering validation when properties change

The SetProperty method in the ValidatableBindableBase class performs validation when a model property is set to a new value. The ValidatableBindableBase.SetProperty calls the BindableBase.SetProperty method, and then performs validation of the property value if it has changed. For more info about Prism’s internal implementation of this see Validating user input in AdventureWorks Shopper.

Summary

In this blog post I’ve created a model class with validation support. The Person class derives from Prism’s ValidatableBindableBase class, and has a property, Name, that possesses data annotation attributes that derive from the ValidationAttribute class to specify validation rules. When the value of the Name property changes validation is performed by calling the ValidatableBindableBase.SetProperty method.

In my next blog post I’ll hook up the model class with code that notifies the user of any validation errors.

Monday, 15 July 2013

Creating a Flyout in C++/CX

Previously I’ve blogged about creating a Flyout using Prism for the Windows Runtime. I thought it would be useful to have a similar Flyout control available in the C++/CX version of my sample PhotoViewer app. Therefore I decided to write a Flyout control in C++/CX, similar to to Prism’s FlyoutView.

Therefore, in this blog post I’ll further extend the PhotoViewer C++/CX sample app so that a Flyout can be displayed by tapping a photo on the PhotoView page. The Flyout will display basic photo information including filename, file type, resolution, and path. A series of value converters will be used to convert the photo information into a user friendly format for display.

Please note that this blog post and sample app use the Flyout control I’ve written, not the new Flyout control which is available in Windows 8.1.

Implementation

Creating the Flyout control

The Flyout class provides the behaviour for the Flyout control. It implements the IFlyout interface, which specifies that an Open method must be provided by implementing classes. The class constructor creates a new Popup control, which will be used to display the Flyout, sets the IsLightDismissEnabled property to true and gets the Frame control for the app.

Flyout::Flyout(int flyoutSize) : m_flyoutSize(flyoutSize)
{
    m_popup = ref new Popup();
    m_popup->IsLightDismissEnabled = true;
    m_frame = safe_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);
}

The Open method initializes the Flyout control for display, initializing different properties and registering event handlers for the Activated and Closed events. These event handlers simply define logic to be executed when the Popup is closed and when the window completes activation, and includes de-registering the event handlers to prevent memory leaks.

void Flyout::Open(Object^ parameter)
{
    ...
        auto viewModel = safe_cast<IFlyout^>(DataContext);
        if (viewModel != nullptr)
        {
            viewModel->Open(parameter);
        }
    ...
}

Once the Flyout is opened the Open method of the view model class that implements the Flyout behaviour is invoked. This provides the view model class with an opportunity to perform any logic that is required to display any data on the Flyout.

Creating the Flyout view

The PhotoInformationFlyoutView derives from the Flyout class.

<local:Flyout x:Class="PhotoViewer.PhotoInformationFlyoutView"
              xmlns:local="using:PhotoViewer"
              ...
              DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=PhotoInfoFlyoutVM}">

The PhotoInformationFlyoutView simply binds to the sub-properties of the File property in the PhotoInformationFlyoutViewModel class. The PhotoInformationFlyoutView is associated with the PhotoInformationFlyoutViewModel class by binding to the PhotoInfoFlyoutVM property of the ViewModelLocator class.

The PhotoInformationFlyoutView constructor must specify the width of the Flyout. The StandardFlyoutSize class provides two standard sizes for Flyouts – Narrow and Wide.

PhotoInformationFlyoutView::PhotoInformationFlyoutView() : Flyout(StandardFlyoutSize::Narrow)
{
    InitializeComponent();
}
Creating the Flyout view model

The PhotoInformationFlyoutViewModel derives from the ViewModelBase class in order to provide property change notification, and implements the IFlyout interface. As previously mentioned, this interface specifies that implementing classes must implement an Open method.

FileInformation^ PhotoInformationFlyoutViewModel::File::get()
{
    return m_file;
}
 
void PhotoInformationFlyoutViewModel::File::set(FileInformation^ value)
{
    if (value != m_file)
    {
        m_file = value;
        OnPropertyChanged("File");
    }
}
 
void PhotoInformationFlyoutViewModel::Open(Object^ parameter)
{
    File = safe_cast<FileInformation^>(parameter);
}

In addition, the PhotoInformationFlyoutViewModel class provides a File property of type FileInformation. When the Open method is called by the FlyoutService class, the File property is set to the received FileInformation parameter. This ensures that the PhotoInformationFlyoutView, which binds to the File property of the PhotoInformationFlyoutViewModel class, has data to display.

Displaying the Flyout

The FlyoutService class provides a service that allows a Flyout to be displayed. It implements the IFlyoutService interface, which specifies that a ShowFlyout method must be provided by implementing classes.

The FlyoutService constructor simply registers an event handler for the SizeChanged event, with the destructor deregistering this event handler in order to prevent memory leaks. This event will fire when the window has rendered or changed its rendering size and is used here with the ShowFlyout method to ensure that a Flyout will be displayed when the app is snapped.


void FlyoutService::ShowFlyout(Object^ parameter, IFlyout^ flyout)
{
    if (ApplicationView::Value == ApplicationViewState::Snapped)
    {
        m_isUnsnapping = true;
        m_parameter = parameter;
        m_flyout = flyout;
        ApplicationView::TryUnsnap();
    }
    else
    {
        if (flyout != nullptr)
        {
            flyout->Open(parameter);
        }
    }
}

The ShowFlyout method will display the Flyout by invoking the Open method of the Flyout class. If the app is in a snapped state it will attempt to unsnap the app, which causes the SizeChanged event handler to be executed, which will in return call the ShowFlyout method to display the Flyout.

The FlyoutService is created as a singleton in the constructor of the ViewModelLocator object. Then, when the PhotoView page is associated with the PhotoViewModel class, by the PhotoVM property of the ViewModelLocator object, a new instance of the PhotoInformationFlyoutView class is created and passed into the PhotoViewModel class, along with the FlyoutService.

PhotoViewModel^ ViewModelLocator::PhotoVM::get()
{
    if (nullptr == m_photoInformationFlyoutView)
    {
        m_photoInformationFlyoutView = (Flyout^)ref new PhotoInformationFlyoutView();
    }
    return ref new PhotoViewModel(m_repository, m_flyoutService, m_photoInformationFlyoutView);
}

The PhotoInformationFlyoutView is displayed by tapping on a photo on the PhotoView page. The Image control in the PhotoView page uses the ImageTappedBehaviour attached behaviour to handle the Tapped event in the PhotoViewModel class.

<Image local:ImageTappedBehaviour.Command="{Binding ShowFlyoutCommand}"
       HorizontalAlignment="Center"
       Source="{Binding Photo}"
       VerticalAlignment="Center" />

The ShowFlyoutCommand is initialized in the PhotoViewModel constructor, to execute the ShowFlyout method.

void PhotoViewModel::ShowFlyout(Object^ parameter)
{
    (*m_flyoutService)->ShowFlyout(m_file, m_flyout);
}

The ShowFlyout method uses the FlyoutService instance, which is injected as a constructor parameter. to call the FlyoutService.ShowFlyout method to display the PhotoInformationFlyoutView. In the call to the ShowFlyout method the m_file parameter specifies the FileInformation object that is passed into the PhotoInformationFlyoutViewModel class, with the m_flyout parameter specifying the Flyout to be displayed (in this case the PhotoInformationFlyoutView). The m_flyout instance is injected into the PhotoViewModel class as a constructor parameter.

The end result of all this is that the PhotoInformationFlyoutView is displayed when a photo on the PhotoView page is tapped.

Summary

In this blog post I’ve extended the sample PhotoViewer C++/CX app so that a Flyout can be displayed by tapping on the photo on the PhotoView page. The PhotoInformationFlyoutView displays basic photo information including filename, file type, resolution, and path. A series of value converters are used to convert the photo information into a user friendly format for display.

The PhotoInformationViewFlyout derives from the Flyout class, with the PhotoInformationFlyoutViewModel class implementing the IFlyout interface. The ShowFlyout method of the FlyoutService class is used to programatically display the PhotoInformationFlyoutView.

The sample app can be downloaded here.

Monday, 8 July 2013

Adding items to the Settings pane using Prism for the Windows Runtime

Previously I extended the sample photo viewing app so that a Flyout can be displayed by tapping on the photo on the PhotoPage. The PhotoInformationFlyout displays basic photo information including filename, file type, resolution, and path. A series of value converters were used to convert the photo information into a user friendly format for display.

In this blog post I’ll further extend the app so that the Settings pane contains an item for the app’s privacy policy. If an app has the ability to transmit data, it must contain a privacy policy. For more info see Windows 8 app certification requirements. While this app does not transmit data, adding a privacy policy to the app is a suitable example for showcasing another feature of Prism for the Windows Runtime, namely that of adding items to the Settings pane. When the user invokes the Settings pane from any page of the app they will see an item named Privacy policy. Selecting this item will display a Flyout that displays the app’s privacy policy.

Implementation

Creating the Flyout view

A Flyout view is required to display the app’s privacy policy. However it does not require an associated Flyout view model, as the Flyout view does not need to bind to any data in a view model, instead displaying embedded text. Please note that in a real app a Flyout view model would most likely be required in order to handle user acknowledgement of the privacy policy, and to obtain the localized version of the privacy policy from a resource file. 

The sample app defines a Flyout view named PrivacyPolicyFlyout which simply includes a TextBlock to display the text of the privacy policy. For more info about creating Flyout views using Prism see my previous blog post.

<Grid Style="{StaticResource PhotoViewerLayoutRootStyle}">
    <Grid.RowDefinitions>
        <RowDefinition Height="80" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TextBlock Margin="20,50,0,0"
               Style="{StaticResource SubheaderTextStyle}"
               Text="Privacy policy" />
    <TextBlock Grid.Row="1"
               Margin="20,50,20,0"
               Style="{StaticResource BasicTextStyle}"
               Text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." 
               TextWrapping="Wrap"/>
</Grid>
Adding an item to the Settings Pane

The PrivacyPolicyFlyout can be displayed by the Settings pane by overriding the GetSettingsCharmActionItems method from the MvvmAppBase class in your App class and adding code to add the item to the Settings pane.

protected override IList<SettingsCharmActionItem> GetSettingsCharmActionItems()
{
    var settingsCharmActionItems = new List<SettingsCharmActionItem>();
    settingsCharmActionItems.Add(new SettingsCharmActionItem("Privacy policy", () => FlyoutService.ShowFlyout("PrivacyPolicy")));
    return settingsCharmActionItems;
}

In this method a new SettingsCharmActionItem is created and added to a List of SettingsCharmActionItems. The SettingsCharmActionItem takes two parameters – the first represents the text to shows in the Settings pane, with the second representing the action to be performed when the SettingsCharmActionItem is selected. So here, when the user selects the Privacy policy text in the Settings pane, the PrivacyPolicyFlyout will be displayed by invoking the ShowFlyout method of Prism’s FlyoutService class.

Summary

In this blog post I’ve extended the app so that the Settings pane contains a Privacy policy item. Prism’s SettingsCharmActionItem class is used to define a Settings pane item and the action that will be performed when the item is selected. When the privacy policy item is selected Prism’s FlyoutService is used to display the PrivacyPolicyFlyout view.

The sample app can be downloaded here.