Windows 8 panels overview

I continue learning Windows 8 programming model and in this post I’ll describe available panels.
Windows 8 provides the following panels for creating UIs:

  • Canvas. Child elements are positioned by relative coordinates.
  • Grid. Consists of columns and rows.
  • StackPanel. Child elements are arranged in a single line which can be either horizontal or vertical.
  • VirtualizingStackPanel. The same class as the StackPanel class but it visualizes only those items which are currently visible.
  • VariableSizedWrapGrid. The similar class to the WrapPanel control which exist in WPF. Elements are positioned in the sequential order and go to the next line if there isn’t enough size.

I’ll explain some panels in detail.
Canvas
This class isn’t different from the WPF class at all. Here is the example with two controls which are situated at different positions.

    <Canvas Background="Black">
        <TextBlock FontSize="22" Canvas.Left="20" Canvas.Top="40">Canvas</TextBlock>
        <Rectangle Canvas.Left="60" Canvas.Top="90" Fill="Green" Height="38" Width="93"  />
    </Canvas>

StackPanel
The obvious difference is that buttons are not stretched by defaults. But in other respects everything is the same.

    <StackPanel Orientation="Vertical" Background="Black">
        <Button>Button 1</Button>
        <Button HorizontalAlignment="Center">Button 2</Button>
        <Button HorizontalAlignment="Stretch">Button 3</Button>
    </StackPanel>

Grid
Almost no difference from its WPF counterpart.

    <Grid Background="Black">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <TextBlock FontSize="20" Margin="5,0,0,0" VerticalAlignment="Center" Text="Row 1"/>
        <TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="5" Margin="0, 0, 5, 0" Text="Column 1" />
        <Button Grid.Row="1">Row 2</Button>
        <Button Grid.Row="1" Grid.Column="1">Column 1</Button>
    </Grid>

VariableSizedWrapGrid
As far as I already said, this class is almost the same as the WPF WrapPanel class. But additionally it has 2 new properties: VariableSizedWrapGrid.ColumnSpan and VariableSizedWrapGrid.RowSpan. The ColumnSpan property is used with the Orientation=Horizontal, and the RowSpan property with the vertical orientation. These properties contain an integer number as a value and if to set it higher than 1, the panel will multiply the space for the element.
Here is the example:

    <VariableSizedWrapGrid Background="Black" Orientation="Horizontal">
        <Button>Button 1</Button>
        <Button VariableSizedWrapGrid.ColumnSpan="2">Button 2</Button>
        <Button>Button 3</Button>
        <Button VariableSizedWrapGrid.ColumnSpan="3" HorizontalAlignment="Stretch">Button 4</Button>
        <Button>Button 5</Button>
    </VariableSizedWrapGrid>

And that’s how it is displayed depending on the available size.
800px

if to narrow to 400px

and 300 px

There are two additional panels: CarouselPanel and WrapGrid. But the CarouselPanel class can’t be used outside the ComboBox class (it is used as the default ItemsPanelTemplate), and the WrapGrid class also should be situated inside a ItemsControl class. Maybe in the release version they will be available for using in any places, but so far we can use only 5 above described panels.

Advertisements

Windows 8 Hello World

I’ve just installed the beta version of Windows 8 to know how it looks before the official release. There are many differences and I’m not accustomed with many of them yet, but I’m sure that much will be changed until the final version, so I’ll not complain.
The most evident change is the new Start Menu button and consequent behavior. There is no that start menu with applications and settings which we can see in Windows 7 now, instead of that it displays this list of large rectangular icons similar to Windows Phone 7:

If you want to return to the habitual desktop, you can either select the Desktop tile among other tiles or use the key combination Alt+Tab.
Here in this post I’ll describe how to create a simple application for new start screen using new Visual Studio 11. The final result consist of one string and looks so:

The full sequence of actions I’ll describe inside the post.
Read more of this post

WPF and Silverlight Validation with IDataErrorInfo and INotifyDataErrorInfo

In this post I’ll describe how to use the IDataErrorInfo and INotifyDataErrorInfo interfaces to perform validation in WPF and Silverlight.
There are several kinds of validations and the preferrable approach in the MVVM pattern is using the IDataErrorInfo or INotifyDataErrorInfo interface.
But this approach doesn’t behave as expected: it performs validation immediately after the launch of the view, whereas it would be better if the validation started only after a user has changed values. Also I would like to reuse some commonly used rules.

So I’ve created the helper class which performs all the necessary work. This class is similar to the class from the FluentValidation library, but it has less code and more flexible to me.
Here is the example of such validation:

    public class PersonViewModel : IDataErrorInfo, INotifyPropertyChanged
    {
        private ModelValidator _validator = new ModelValidator();

        public PersonViewModel()
        {
            //Six validation rules
            this._validator.AddValidationFor(() => this.FirstName).NotEmpty()
				.Show("Enter a First Name");
            this._validator.AddValidationFor(() => this.LastName).NotEmpty()
				.Show("Enter a Last Name");

            this._validator.AddValidationFor(() => this.Age).NotEmpty()
				.Show("Enter an age");
            this._validator.AddValidationFor(() => this.Age).Between(0,99)
				.Show("The age must be between 0 and 99");

            this._validator.AddValidationFor(() => this.Email)
				.When(() => this.IsSubscribe).NotEmpty()
				.Show("Enter an email address");
            this._validator.AddValidationFor(() => this.Email)
				.When(() => this.IsSubscribe).EmailAddress()
				.Show("Enter a valid email address");
            //Validates on changes of properties
            this.PropertyChanged += (s, e) => this._validator.ValidateProperty(e.PropertyName);
        }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string this[string columnName]
        {
            get { return this._validator.GetErrors(columnName).FirstOrDefault(); }
        }

There is only 4 steps:
1. Create a variable of the ModelValidator type
2. Add necessary validation rules
3. Update validation every time when a property has been changed
4. Return cached errors inside the indexer property.

Actually it is not so obligatory to implement the 3rd step and update validation inside the PropertyChanged event handler. You can remove that line and call the ValidateAll method after a user clicks the Save button. But validation on changes is more preferrable solution.

I’ve added some predefined validation rules, if they aren’t enough, you can use the Must method with your own functions.
1. NotNull – the property value shouldn’t be null.
2. NotEmpty – if the property is of the string type, checks whether the string is null or consists of whitespaces. If of any other type – this rule is the same as NotNull.
3. Between – checks whether the property value is within a specific range. Works with strings as well as with numbers, so it’s not necessary to parse strings in view models.
4. EmailAddress – if the string value isn’t null, it should be a valid e-mail address.
5. Must – any user-defined validation function. For example: this._validator.AddValidationFor(() => this.LastName).Must(() => this.LastName.Length < 10).Show("Last name should not exceed 10 characters");

To implement this validation, you should copy 3 files with 2 classes to your project.
Here is the completed project where you can take all the necessary classes: WpfValidation.zip

Update
I’ve also added the validation for Silverlight both with IDataErrorInfo and INotifyDataErrorInfo:
The image illustrating validation errors in Silverlight
The source code you can download here: SilverlightValidation.zip