Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

Archive for Silverlight

October 25, 2013

Who Moved My Cheese: RIA Services

Filed under: ASP.NET RIA Services,C#,Silverlight,VB.NET @ 9:22 am

WCF RIA Services was (past tense) an awesome technology that allowed developers to quickly and super easily build domain classes and WCF services for Silverlight applications.

In VS 2012 (and VS 2010 SP1), you could use Add | New Item and get a template for a WCF RIA Domain Service Class.

image

(If you are still using VS 2012 or VS 2010 SP1+ with RIA Services, see this set of blog posts for samples and tips.)

In VS 2013, attempting to find the Domain Service Class template gives you this:

image

As of July 3, 2013, WCF RIA Services was open sourced and renamed Open RIA Services. The project lead is my friend, Colin Blair, whose name you know if you have ever had a question about WCF RIA Services.

To ensure your Silverlight/WCF RIA Services applications still run in Visual Studio 2013, Microsoft included WCF RIA Services V1.0 "in the box". This provides the compile-time domain class and service code generation as well as the runtime functionality that makes the domain service work. So you don’t have to do anything extra to run or debug your existing VS 2012 Silverlight applications in Visual Studio 2013.

However, the following features are gone:

  • The Business Application project template
  • The Domain Service Class template and associated wizard
  • Toolbox items for the Silverlight designer surface
  • Data Sources window integration for the Silverlight designer surface

See this post for more information on the above changes.

Microsoft has published several NuGet packages for support of Entity Framework 5, Windows Azure, and the SOAP and JSON endpoints in WCF RIA Services. See this post for more information on the NuGet packages.

To follow the Open RIA Services project, see this blog. (Click on "Navigation" to open the menu and navigate the blog.)

Enjoy!

EDIT: Clarified that the VS 2013 RIA Services features don’t require changes when opening VS 2012 Silverlight projects.

January 21, 2013

Tips for Building a BO for Silverlight and RIA

Filed under: ASP.NET RIA Services,C#,Silverlight,VB.NET @ 2:13 pm

The following are some tips when building a business object class for use by Silverlight and RIA services.

NOTE: This assumes you are not using Entity Framework (EF).

Use Class-Level Validation

Specifying class-level validation allows you to perform validation on the entire class. This is a good location for cross-field validation.

For example, say you are creating a Discount class that defines discounts available to your customers. A percentage discount must be less than 100% where a dollar discount can be any amount. In the class-level validation, you can check the discount type against the amount to determine if the fields are valid.

Use the CustomValidation attribute to define class-level validation:

In C#:

[CustomValidation(typeof(DiscountValidation), "ValidateDiscount")]
public class Discount

In VB:

<CustomValidation(GetType(DiscountValidation), "ValidateDiscount")>
Public Class Discount

Define a Key

For WCF RIA Services to recognize your objects, they must have a unique key. In most business objects, this is easy because every object relates to a database row that already has a unique key.

In the above Discount example, the discount already has a unique DiscountId associated with it.

Use the Key attribute to define the key field.

In C#:

private int _DiscountId;
[Key()]
public int DiscountId {
    get { return _DiscountId; }
    set 
   
{
        if (!_DiscountId.Equals(value))
        {
            // Set the value
            _DiscountId = value;
        }
    }
}

In VB:

Private _DiscountId As Integer
<Key>
Public Property DiscountId() As Integer
    Get
        Return _DiscountId
    End Get
    Set(ByVal value As Integer)
        If Not _DiscountId.Equals(value) Then
            ‘ Set the value
            _DiscountId = value
        End If
    End Set
End Property

NOTE: If you ever have an issue whereby your WCF RIA Service is returning one row when you know you have many rows, chances are that the Key attribute is missing. Without this attribute, RIA views all rows as the same row and therefore only returns one.

Add a String Property for each Numeric Property

If you define a numeric property in your business object, such as an Integer or Decimal, and bind it in Silverlight, Silverlight will automatically convert any entered value to a number. If the user enters "one", it won’t generate a validation error. Silverlight instead converts it to a number. Any string converted to a number is 0.

This may not seem likely, but consider the possibility that the user enters 50%. Because of the "%" sign, Silverlight will convert the value to 0 and consider it a valid number.

To have full control over numeric entry, create a string version of any numeric property. Define a Regular Expression to validate that string as an integer or decimal value. And bind that string value to the Silverlight field.

In C#:

[RegularExpression("^([0-9]*\\,?[0-9]+|[0-9]+\\,?[0-9]*)?$",
errormessage = "Enter a dollar amount or percent value.")]
public string AmountString {
    get { return Amount.ToString("N2"); }
    set { decimal.TryParse(value, Amount); }
}

In VB:

<RegularExpression("^([0-9]*\,?[0-9]+|[0-9]+\,?[0-9]*)?$", errormessage:="Enter a dollar amount or percent value.")>
Public Property AmountString() As String
    Get
        Return Amount.ToString("N2")
    End Get
    Set(value As String)
        Decimal.TryParse(value, Amount)
    End Set
End Property

Add a Property for any Related Data

When updating data, RIA is much easier to work with if it manages related child data as a part of the parent data.

For example, say a discount is only applied to certain product types: downloadable software products allow one set of discounts, while sending CDs has a different set of available discounts. So a single discount has a set of products that it relates to.

To more easily edit this related data, create a property for the child data in the parent business object. Mark the relationship with the Association and Include attributes.

In C#:

[Include()]
[Association("Discount_Product", "DiscountId", "DiscountId")]
public List<Product> ProductList { get; set; }

In VB:

<Include>
<Association("Discount_Product", "DiscountId", "DiscountId")>

Public Property ProductList As List(Of Product)

Enjoy!

May 14, 2011

Tech Ed 2011: Source Code for My Talk

Filed under: ASP.NET RIA Services,General,Silverlight @ 2:00 pm

I am presenting "Microsoft Silverlight, WCF RIA Services, and Your Business Objects" at the Tech Ed 2011 conference in Atlanta on May 18, 2011.

You can get the code for my talk from my company’s Web site. Look for the Tech Ed 2011 entry.

If you are at Tech Ed, come by and say hi. I will be at the Silverlight booth on Monday night and on Wednesday afternoon.

Enjoy!

May 4, 2011

Silverlight/WCF RIA Validation: Metadata Class

Filed under: ASP.NET RIA Services,C#,Silverlight @ 1:05 am

Data annotation attributes are a great way to add single property validation to your Silverlight/WCF RIA application. But what if you don’t want to inject attributes all over your business classes? The purpose of a metadata class is to have a place for all of these attributes external from the business class.

NOTE: This post is part of a set of validation posts which starts here and it uses the sample code from this prior post.

If your Silverlight application uses WCF RIA services and your own business objects, then you can set attributes on your business object properties to define single-attribute validation.

In this prior post, the code example demonstrated how to use the single property validation attributes available to validate that a last name is entered and does not exceed 20 characters, the attributes look like this:

[Required(ErrorMessage = "Please enter a last or family name.")]
[StringLength(20, ErrorMessage = "Last name cannot exceed 20 characters.")]
public string LastName { get; set; }

If you don’t want these attributes in your business classes, you can instead create a metadata file and store all of the attributes there.

1) Right-click on your business object’s Class Library project and add a new class (Add | New Item | Class).

In this example, the class was called Student. So the metadata class is named StudentMetadata.cs.

2) In  this new class, add any of the business object properties and associated attributes.

Note that the property names defined in the metadata class must exactly match the property names in the original class.

In C#:

using System.ComponentModel.DataAnnotations;

namespace InStepValidationExample.BL
{
internal sealed class StudentMetadata
{

   /// <summary>
   /// Private to ensure this class is not instantiated.
   /// </summary>
   private StudentMetadata()
   {}

  [Required(ErrorMessage = "Please enter a last or family name.")]
  [StringLength(20, ErrorMessage = "Last name cannot exceed 20 characters.")]
  public string LastName { get; set; }
}
}

In VB:

TBD

3) Associate the metadata class with its original class using a MetadataType attribute on the original class definition. This attribute associates the original business object class with the metadata class.

In C#:

namespace InStepValidationExample.BL
{
    [MetadataType(typeof(StudentMetadata))]
    public class Student
    {
     …
    }
}

In VB:

TBD

When you run the application, the validation should work as before:

image

Use this technique any time you want attributes on your business object properties, but want to define these attributes external from the business object classes.

Enjoy!

May 3, 2011

Silverlight Validation: Resource File

Filed under: ASP.NET RIA Services,C#,Silverlight @ 2:04 am

Resource files are a great way to manage strings, especially if you need to support multiple languages. This post demonstrates how to use a resource file with the validation attributes used by Silverlight and WCF RIA Services.

NOTE: This post is part of a set of validation posts which starts here and it uses the sample code from this prior post.

In this prior post, the code example demonstrated how to use the single property validation attributes available in Silverlight and WCF RIA Services. For example, to validate that a first name is entered and does not exceed 20 characters, the attributes look like this:

[Required(ErrorMessage="Please enter a first name.")]
[StringLength(20, ErrorMessage = "First name cannot exceed 20 characters.")]
public string FirstName { get; set; }

Notice how the validation error messages are hard-coded strings. This poses a challenge if you need to localize your application.

A better option is to add the strings to a resource file. The trick here is that the resource file needs to exist both on the server (in the Class Library project if you are using WCF RIA with your own business layer) and on the client (in the Silverlight project). This is done by a process called linking.

1) In the Class Library project containing your business layer, add a resource file (Add | New Item | Resources File).

I added mine to a Resources folder in the project.

NOTE: If you are not using your own business layer on the server, you can add the resource file directly to the Web project instead.

2) Enter a name for each string along with the string values. Optionally add a comment.

3) Set the Access Modifier for each resource string to Public.

The result should look something like this:

image

4) In the Silverlight project, link to that resource file by selecting Add | Existing Item and then clicking on Add As Link in the Add Existing Item dialog.

image

5) In the Silverlight project, link also to the associated Designer.cs file.

NOTE: The Add Existing Item dialog allows multiple selection. So you could link both the rex file and the Designer/cs file in one step.

6) Modify the attribute parameters in the business layer Class Library project to reference the resource file instead of using hard-coded strings. Be sure to add a using for the resource file’s namespace:

using InStepValidationExample.BL.Resources;

[Required(ErrorMessageResourceType = typeof(ValidationErrorResources),
ErrorMessageResourceName = "FirstNameRequired")]
[StringLength(20,
    ErrorMessageResourceName = "FirstNameLength",
    ErrorMessageResourceType = typeof(ValidationErrorResources))]
public string FirstName { get; set; }

Instead of setting the ErrorMessage parameter to a hard-coded string, this code sets the ErrorMessageResourceType parameter to the type of the resource file (which is the resource file name). The ErrorMessageResourceName parameter specifies the name that you defined for the associated resource string in the resource file.

7) Now for the tricky part. By default, Visual Studio requires that the two resource files be in the same namespace. If they aren’t, the application won’t find the resources.

For example, if you use the Silverlight Business Application template, you can see that it puts  the resource file in the BizApp.Web project under a Resources folder. The resources are then in the BizApp.Web.Resources namespace.

To access the resources from the BizApp Silverlight project, the file is put in a folder hierarchy with a Web folder and then a Resources folder so the resulting namespace is again BizApp.Web.Resources.

image

In the example for this post, however, the resources are in a Class Library in a business layer separate from the Web project:

image

The namespace of the resources in the business layer is InStepValidationExample.BL.Resources. The namespace of the resources in the Silverlight project is InStepValidatoinExample.SL.Resources.

So if you run the application at this point, it will crash with a "TargetInvocationException occurred" message. If you look at the exception detail it says "Could not find any resources appropriate for the specified culture or the neutral culture…" Basically, it cannot find the resource file.

Luckily, we know the secret handshake required to get this to work:

7a) Right-click on the Silverlight project and select Unload Project.

7b) Right-click on the Silverlight project again and select to edit the project file.

7c) Add a <LogicalName> element to the <EmbeddedResource> element in the project file and set it to the namespace and resource name. Mine looked like this:

<ItemGroup>
  <EmbeddedResource Include="..\InStepValidationExample.BL\Resources\ValidationErrorResources.resx">
    <Link>Resources\ValidationErrorResources.resx</Link>
    <LogicalName>
  InStepValidationExample.BL.Resources.ValidationErrorResources.resources
     </LogicalName>

  </EmbeddedResource>
</ItemGroup>

7d) Close the project file.

7e) Right-click on the Silverlight project and select Reload Project.

Now when you run, it should find your resource file.

image

Use a resource file any time you want better management of your strings, especially if you plan to localize your application.

Enjoy!

May 1, 2011

Silverlight/WCF RIA Single Property Validation

Filed under: ASP.NET RIA Services,C#,Silverlight @ 9:01 pm

When you identify the validation scenarios for your application, you will find that some only require basic single property validation. Examples:

  • Ensure that a first name is entered.
  • Ensure that the first name is not longer than 20 characters
  • Ensure that the age is between 16 and 120.
  • Ensure that the email address is valid.

NOTE: This post is part of a set of validation posts which starts here and it uses the sample code from this prior post.

Each of these requirements can be handled by Silverlight’s single field validation using property attributes.

When you use WCF RIA Services and your own set of business objects, these attributes are set in the business layer on the business object properties. WCF RIA Services then automatically generates a copy of your business object properties with their attributes on the client for use with Silverlight.

Silverlight performs the validation when the user leaves the field AND before the data is submitted to the server. If there is a validation error, the data is not submitted to the server and a validation error appears.

Each of the simple validation attributes are discussed below.

Required Field Validation

Use the Required attribute to mark a property as required. For example, if the first name is required, the first name property is adorned as follows:

[Required()]
public string FirstName { get; set; }

If you make this change and run the sample application (from this prior post), the first name field is automatically validated. Clear the field and you will see this:

image

Silverlight’s built-in validation automatically kicks in and you see the default required validation error message.

NOTE: You can modify the Silverlight XAML to specify the ValidatesOnNotifyDataErrors property as part of the binding expression. However, this is not necessary. The default value of this property is true, so the validation errors are reported by default.

If you don’t like the error message, you can change it by setting one of the named parameters of the Required attribute:

[Required(ErrorMessage="Please enter a first name.")]
public string FirstName { get; set; }

The message then appears as shown below:

image

Use required field validation any time you want to ensure that the user enters a value into a Silverlight control.

String Length Validation

Often times the data entered on a page in Silverlight will get stored to a database where a maximum field size is defined. It is helpful for the users to be aware of this maximum before attempting to submit the data to the server.

For example, if the first name is set to a maximum of 20 characters in the database, you can set the StringLength attribute as follows:

[Required(ErrorMessage="Please enter a first name.")]
[StringLength(20, ErrorMessage = "First name cannot exceed 20 characters.")]
public string FirstName { get; set; }

Use string length validation any time you want to ensure that the user does not enter more data than can be stored in the database table or any other time that a string length cannot exceed a maximum value.

Range Validation

When entering numbers, often times the value must be limited to a specific range of values. For example, in this application the age must be between 16 and 120.

[Range(16, 120,
ErrorMessage="Please enter your age. You must be 16 or older.")]
public int Age { get; set; }

This results in the following:

image

NOTE: The Range attribute has overloads with parameters that are integers or doubles. To validate other types (such as decimal), you need to use the Range overload that takes a type as the first parameter and string values to convert to the defined type. For example:

[Range(typeof(Decimal),"0", "40000")]
public decimal TuitionPaid{ get; set; }

Use range validation any time you want to validate user entry to a range of numeric values.

Regular Expression Validation

Regular expression validation allows you to perform pattern matching on the entered value. For example, an email address must match a specific pattern with a local part of the address followed by an at sign (@) followed by a domain name. The Regular Expression attribute could look like this:

[Regular(@"^(?("")("".+?""@)|" +
      @"(([0-9a-zA-Z]((\.(?!\.))|" +
      @"[-!#\$%&’\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))" +
      @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|" +
      @"(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$",
      ErrorMessage="Please enter a valid email address")]

public string Email { get; set; }

NOTE: Replace "Regular" above with "RegularExpression". For whatever reason, the entire string was blocked in this post if the word "Expression" appeared above.

Other properties that could use a regular expression include phone numbers, social security numbers, and any other entry that must match a specific pattern.

You can find more information on regular expressions here.

Use regular expressions any time you want to validate a user’s entry based on pattern matching.

For more complex validation scenarios, see this prior post.

Enjoy!

EDIT 5/2/11: Corrected typographical errors. Corrected the regular expression, which did not paste into the post correctly.

Silverlight MVVM, WCF RIA Services Simple Sample Application

Filed under: ASP.NET RIA Services,C#,Silverlight @ 5:52 pm

This post provides a simple Silverlight MVVM, WCF RIA Services sample application that is used to demonstrate validation techniques. The sample application is provided in this separate post so it can be readily used with any of the presented validation techniques.

NOTE: This post defines a sample application that is used in the validation scenarios presented in this prior post.

The application is a simple data entry form for entering basic student information.

image

To create this application, follow these steps.

1) Build four projects:

  1. C# or VB Class Library project defining the business layer. (This is NOT a Silverlight class library.)
  2. C# or VB Silverlight Application project. (Be sure to check the Enable WCF RIA Services checkbox.)
  3. C# or VB ASP.NET Web project. (This project is automatically created when creating the Silverlight Application project).
  4. C# or VB Silverlight Class Library project. (For the library functions, such as commanding.)

2) In the first Class Library project (the one that is NOT a Silverlight class library), build a Student business object.

In C#:

using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;

namespace InStepValidationExample.BL
{
    public class Student
    {
        public int Age { get; set; }

        public string Email { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public DateTime? RegistrationDate { get; set; }

        [KeyAttribute]
        public int StudentId { get; set; }

        public DateTime? VaccinationDate { get; set; }

        public bool? VaccinationOptOut { get; set; }

        public static Student Retrieve(int id)
        {
            var student = new Student
            {
                StudentId = id,
                LastName = "Baggins",
                FirstName = "Bilbo",
                Age = 111,
                Email =
testemail@live.com,
                VaccinationOptOut = true,
                RegistrationDate = DateTime.Now
            };
            return student;
        }

        public bool Save()
        {
            // Code that saves the changes to the database;
            Debug.WriteLine("Saving: " + LastName + ", " + FirstName);
            return true;
        }
    }
}

In VB:

TBD

This code defines a set of simple properties for a student. The StudentId property is marked with the KeyAttribute, which defines a unique Id for the entity. This attribute is required for this entity to work with WCF RIA Services.

The Retrieve and Save methods in this example are "fake" methods. You would need to replace the code in these methods with code to retrieve and save the student from a data store such as a database. By using the fake code for this, you can try out the validation techniques  without needing to build or access a database.

3) In the ASP.NET Web application, build a Student Domain Service class.

In C#:

namespace InStepValidationExample.SL.Web
{
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using InStepValidationExample.BL;

    [EnableClientAccess()]
    public class StudentService : DomainService
    {

        public Student GetStudentById(int id)
        {
            return Student.Retrieve(id);
        }

        public void UpdateStudent(Student student)
        {

        }

        protected override bool PersistChangeSet()
        {
            Student changedStudent;
            bool success = true;

            foreach (var item in ChangeSet.ChangeSetEntries)
            {
                if (item.Entity.GetType() == typeof(Student))
                {
                    changedStudent = (Student)item.Entity;
                    success = changedStudent.Save();
                    if (!success)
                        break;
                }
            }
            return success;
        }

    }
}

In VB:

TBD

This code provides the following methods:

  • GetStudentById to get the student from the business layer.
  • UpdateStudent method to enable updating of the student.
  • PersistChangeSet method to parse through the changeSet and save any changed students.

You can add Insert and Delete methods as desired.

4) Build an MVVM base class in the Silverlight project as demonstrated in this prior post.

5) Build a Commanding class in the Silverlight Class Library project as demonstrated in this prior post.

6) Build the ViewModel in the Silverlight Application project.

In C#:

using System;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows.Input;
using InStepValidationExample.BL;
using InStepValidationExample.Library;
using InStepValidationExample.SL.Web;

namespace InStepValidationExample.SL.ViewModels
{
    public class StudentsViewModel : ViewModelBase
    {
        private StudentContext StudentContextInstance;

        private ICommand _CancelCommand;
        public ICommand CancelCommand
        {
            get
            {
                return _CancelCommand;
            }
        }

        private Student _CurrentStudent;
        public Student CurrentStudent
        {
            get
            {
                return _CurrentStudent;
            }
            set
            {
                if (_CurrentStudent != value)
                {
                    _CurrentStudent = value;
                    OnPropertyChanged("CurrentStudent");
                }
            }
        }

        private ICommand _SaveCommand;
        public ICommand SaveCommand
        {
            get
            {
                return _SaveCommand;
            }
        }

        public StudentsViewModel()
        {
            LoadData();
            DefineCommands();
        }

       private void DefineCommands()
       {
         _CancelCommand = new DelegateCommand<Object>
                         (OnCancelCommand);
         _SaveCommand = new DelegateCommand<Object>
                    (OnSaveCommand);
       }

        /// <summary>
        /// Loads the data for the application.
        /// </summary>
        private void LoadData()
        {
            if (IsInDesignModeStatic)
            {
                LoadDesignData();
            }
            else
            {
                // Load the student data asynchronously
                StudentContextInstance = new StudentContext();
                var loadop = StudentContextInstance.Load
                                          (StudentContextInstance.
                                                GetStudentByIdQuery(1),
                                                OnStudentLoaded, null);
            }
        }

        /// <summary>
        /// Loads temporary data for use in the designer.
        /// </summary>
        /// <remarks></remarks>
        private void LoadDesignData()
        {
            //Design mode data
            var student = new Student
            {
                LastName = "Baggins",
                FirstName = "Bilbo",
                Age = 111,
                Email = "testemail@live.com",
                VaccinationOptOut = true,
                RegistrationDate = DateTime.Now
            };

            CurrentStudent = student;
        }

        private void OnCancelCommand(object o)
        {
            StudentContextInstance.RejectChanges();
        }

        private void OnStudentLoaded(LoadOperation lo)
        {
            CurrentStudent =
                StudentContextInstance.Students.FirstOrDefault();
        }

        private void OnSaveCommand(object o)
        {
             StudentContextInstance.SubmitChanges(OnChangesSubmitted,
                                                      null);
        }

        private void OnChangesSubmitted(SubmitOperation so)
        {
             if (so.HasError)
             {
                  so.MarkErrorAsHandled();
             }
        }

    }
}

In VB:

TBD

This code defines two commands: Save and Cancel. It then loads design-time data or at run-time it calls the GetStudentById query to retrieve the student from the business layer.

The OnChangesSubmitted code ensures that any validation errors are correctly marked as handled and don’t cause an unhandled exception in your application (error 4004).

7) Build the View.

<UserControl x:Class="InStepValidationExample.SL.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" 
xmlns:sdk="
http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
xmlns:vms="clr-namespace:InStepValidationExample.SL.ViewModels">

    <UserControl.DataContext>
        <vms:StudentsViewModel />
    </UserControl.DataContext>
   
    <Grid x:Name="LayoutRoot"
          Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid HorizontalAlignment="Center"
              VerticalAlignment="Top"
              DataContext="{Binding CurrentStudent}"
              Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <sdk:Label Content="First Name:"
                       Grid.Column="0"
                       Grid.Row="0"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <TextBox Grid.Column="1"
                     Grid.Row="0"
                     Height="23"
                     HorizontalAlignment="Left"
                     Margin="3"
                     Name="firstNameTextBox"
                     Text="{Binding Path=FirstName,
                            Mode=TwoWay,
                            TargetNullValue=”}"
                     VerticalAlignment="Center"
                     Width="130" />
            <sdk:Label Content="Last Name:"
                       Grid.Column="0"
                       Grid.Row="1"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <TextBox Grid.Column="1"
                     Grid.Row="1"
                     Height="23"
                     HorizontalAlignment="Left"
                     Margin="3"
                     Name="lastNameTextBox"
                     Text="{Binding Path=LastName,
                            Mode=TwoWay,
                            TargetNullValue=”}"
                     VerticalAlignment="Center"
                     Width="130" />
            <sdk:Label Content="Email:"
                       Grid.Column="0"
                       Grid.Row="2"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <TextBox Grid.Column="1"
                     Grid.Row="2"
                     Height="23"
                     HorizontalAlignment="Left"
                     Margin="3"
                     Name="emailTextBox"
                     Text="{Binding Path=Email,
                            Mode=TwoWay,
                            TargetNullValue=”}"
                     VerticalAlignment="Center"
                     Width="130" />
            <sdk:Label Content="Age:"
                       Grid.Column="0"
                       Grid.Row="3"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <TextBox Grid.Column="1"
                     Grid.Row="3"
                     Height="23"
                     HorizontalAlignment="Left"
                     TextAlignment="Right"
                     Margin="3"
                     Text="{Binding Path=Age,
                            Mode=TwoWay,
                            TargetNullValue=”}"
                     VerticalAlignment="Center"
                     Width="130" />
            <CheckBox Grid.Column="1"
                      Grid.Row="4"
                      IsChecked="{Binding VaccinationOptOut,
                                Mode=TwoWay,
                                TargetNullValue=false}"
                      Content="Vaccination Opt Out"/>
            <sdk:Label Content="Vaccination Date:"
                       Grid.Column="0"
                       Grid.Row="5"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <sdk:DatePicker Grid.Column="1" 
                        Grid.Row="5" 
                        Height="23" 
                        HorizontalAlignment="Left" 
                        Margin="3" 
                        SelectedDate="{Binding Path=VaccinationDate,
                                        Mode=TwoWay,
                                        TargetNullValue=”}" 
                        VerticalAlignment="Center" 
                        Width="130" />
            <sdk:Label Content="Registration Date:"
                       Grid.Column="0"
                       Grid.Row="6"
                       HorizontalAlignment="Left"
                       Margin="3"
                       VerticalAlignment="Center" />
            <sdk:DatePicker Grid.Column="1"
                        Grid.Row="6"
                        Height="23"
                        HorizontalAlignment="Left"
                        Margin="3"
                        SelectedDate="{Binding Path=RegistrationDate,
                                        Mode=TwoWay,
                                        TargetNullValue=”}"
                        VerticalAlignment="Center"
                        Width="130" />
        </Grid>

        <StackPanel Grid.Row="1"
                    Orientation="Horizontal"
                    HorizontalAlignment="Right">
        <Button x:Name="SaveButton"
                Content="Save"
                Command="{Binding SaveCommand}"
                Width="75"
                Height="24"
                Margin="5"/>
        <Button x:Name="CancelButton"
                Content="Cancel"
                Command="{Binding CancelCommand}"
                Width="75"
                Height="24"
                Margin="5" />
        </StackPanel>
    </Grid>
</UserControl>

When you have the above code in place, you should see the design-time data appear in the designer.

8) Run and ensure the runtime data appears.

The code displays the form as shown at the top of this post. As you edit the data on the form, note that there is no validation in place. You can type "aaa" into the age. You can delete the first or last name. And you can put in "aaa" into the email address.

See the other posts in this series for information on adding the validation.

Enjoy!

Silverlight MVVM, RIA, and Validation

Filed under: ASP.NET RIA Services,C#,Silverlight,VB.NET @ 5:43 pm

One of the biggest challenges of implementing validation in Silverlight is finding the appropriate technique based on your architecture and goals. There are lots of choices and lots of examples, but not all examples work in all scenarios. Plus many examples demonstrate techniques that are no longer necessary or valid in the current version of Silverlight or when using WCF RIA services.

Below are a set of posts on techniques for performing validation with Silverlight 4.0 using MVVM, WCF RIA Services, and custom business objects.

A few things to keep in mind if you are using Silverlight and WCF RIA Services:

  1. In most cases, the code should not need to throw exceptions for validation errors.
  2. The latest version of Silverlight/RIA provides automatic validation and a built-in validation error dictionary, so you do not have to write any code to build or populate validation errors.

The last point is an important one because there are videos and posts that go through the pages and pages of code required to manage your own validation and validation error dictionary. While this code is necessary and useful if you are using WCF directly, it is not necessary if you are using WCF RIA Services.

Here are the links:

Click on a link to navigate to the desired post.

Enjoy!

March 5, 2011

Silverlight Charting: Formatting the Tick Marks

Filed under: Silverlight @ 4:53 pm

The tick marks on the charts may not look like much, but they can be helpful to clarifying the meaning of your charts.

By default, the tick marks are small little black lines on each axis that identify the axis "ticks". See the following chart. (I put a red circle around one of them since they are a little hard to see.)

image

This prior post sets the ground work for displaying a chart. This post covers how to format the tick marks on the axes.

NOTE: This post is part of a series that starts with this prior post. The example in this post uses the application that is built as part of that series.

If you have a chart on your page, you already have the necessary namespace:

xmlns:toolkit=
  "http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"

To style the axis tick marks, add a CategoryAxis.MajorTickMarkStyle element under the CategoryAxis element within the Chart.Axes element. The XAML is shown below.

<toolkit:Chart.Axes>
    <toolkit:CategoryAxis Orientation="X"
                          Location="Bottom"
                          Foreground="White">
        <toolkit:CategoryAxis.AxisLabelStyle>
            <Style TargetType="toolkit:AxisLabel">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate
                             TargetType="toolkit:AxisLabel">
                            <TextBlock
                           Text="{TemplateBinding FormattedContent}"
                                       TextAlignment="Right"
                                       TextWrapping="Wrap"
                                       Width="50"
                                       Margin="-40,-5,0,26"
                                       RenderTransformOrigin="1,.5">
                                    <TextBlock.RenderTransform>
                                        <RotateTransform Angle="300" />
                                    </TextBlock.RenderTransform>
                            </TextBlock>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </toolkit:CategoryAxis.AxisLabelStyle>
        <toolkit:CategoryAxis.MajorTickMarkStyle>
            <Style TargetType="Line">
                <Setter Property="Stroke"
                        Value="White" />
                <Setter Property="StrokeThickness"
                        Value="2" />
                <Setter Property="Y1"
                        Value="0" />
                <Setter Property="Y2"
                        Value="10" />
                <Setter Property="RenderTransform">
                    <Setter.Value>
                        <RotateTransform Angle="15" />
                    </Setter.Value>
                </Setter>
            </Style>
        </toolkit:CategoryAxis.MajorTickMarkStyle>
    </toolkit:CategoryAxis>
</toolkit:Chart.Axes>

This code sets the color using the Stroke property and the thickness using the StrokeThickness property. It sets the line start and end using the Y1 and Y2 properties. It then uses RenderTransform to angle the tick mark so it matches nicely with the angled text.

The result is shown below.

image

Use this technique any time you want to control the layout and style of the chart tick marks.

Enjoy!

Silverlight Charting: Formatting the Axis

Filed under: Silverlight @ 3:41 pm

When displaying a chart, you may want to format the x and y axes. This post covers how to set the axis font color and wrap and angle the text.

image

This prior post sets the ground work for displaying a chart. This post covers how to format the axis. This example formats the x-axis, but you can use the same technique to format either axis.

NOTE: This post is part of a series that starts with this prior post. The example in this post uses the application that is built as part of that series.

If you have a chart on your page, you already have the necessary namespace:

xmlns:toolkit=
  "http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"

To style the axis, use the CategoryAxis element within the Chart.Axes element. The XAML is shown below.

<toolkit:Chart.Axes>
    <toolkit:CategoryAxis Orientation="X"
                          Location="Bottom"
                          Foreground="White">
        <toolkit:CategoryAxis.AxisLabelStyle>
            <Style TargetType="toolkit:AxisLabel">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate
                              TargetType="toolkit:AxisLabel">
                            <TextBlock
                     Text="{TemplateBinding FormattedContent}"
                                       TextAlignment="Right"
                                       TextWrapping="Wrap"
                                       Width="50"
                                       Margin="-40,-5,0,26"
                                       RenderTransformOrigin="1,.5">
                                    <TextBlock.RenderTransform>
                                        <RotateTransform Angle="300" />
                                    </TextBlock.RenderTransform>
                            </TextBlock>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </toolkit:CategoryAxis.AxisLabelStyle>
    </toolkit:CategoryAxis>
</toolkit:Chart.Axes>

The CategoryAxis element defines the orientation. In this example, the formatting is for the "X" axis. Add a second CategoryAxis element under the Chart.Axes element to format the "Y" axis as well.

The Location property allows you to put the X-axis at the bottom or at the top of the chart. The Foreground property defines the color of the axis text.

The CategoryAxis.AxisLabelStyle allows you to set the template for the axis content. In this example, the style contains a TextBlock, which allows for wrapping and aligning the text.

The Width and Margin adjust the location of the text under the columns. The RenderTransform code angles the text. This is a useful technique if you have text that is long or columns that are close together.

Use this technique any time you want to format or style the chart axes.

Enjoy!

Next Page »

© 2023 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs