Intersoft ClientUI Documentation
Walkthrough: Creating Model For Book Data

This walkthrough discusses how to create Model class that will be used in other walkthrough that uses MVVM Pattern.

This particular walkthrough steps you through the process of creating a Model class for the Book Data.

Preparing the Project Environment

To help you quickly get started with MVVM pattern application development, ClientUI provides a number of MVVM-ready project templates that integrate to Visual Studio 2010. The basic MVVM project templates include base classes such as ModelBase.cs and ViewModelBase.cs as well as several providers to work with dialog boxes in ClientUI. Some advanced MVVM business templates include more comprehensive base classes such as ValidationViewModelBase.cs and EntityValidationViewModelBase.cs to provide built-in error validation that integrates with data annotations in the domain service.

If you use other project templates that does not have base classes mentioned above, it is advised that you prepare these classes before continuing. This section shows how to create the ModelBase class that will be used as the base class for all model objects.

To create ModelBase class

Skip this steps if you are using ClientUI MVVM-ready project templates such as Intersoft ClientUI MVVM Application project template , Intersoft ClientUI MVVM Business Application project template or Intersoft ClientUI Desktop Application.

  1. In your project, create new folder with name Models.
  2. In the Models folder, add new class under with name ModelBase.cs.
  3. Open the ModelBase.cs.
  4. At the ModelBase class, implements both INotifyPropertyChanged and IDataErrorInfo interfaces.
    The INotifyPropertyChanged is one of the fundamental interfaces in Silverlight/WPF that enables the binding engine to perform two-ways data binding, that is, changes in the model can be propagated to the target that bound to that particular model.
    The IDataErrorInfo provides built-in error validation that generally notifies an error to the binding engine.
  5. Define the basic functionality to support both  INotifyPropertyChanged and IDataErrorInfo interfaces as shown in the following code.

    C#

    Copy Code
    public class ModelBase : INotifyPropertyChanged, IDataErrorInfo
    {
        #region Properties
    
        private Dictionary<string, string> _errors = new Dictionary<string, string>();
    
        public virtual bool HasErrors
        {
            get
            {
                return _errors.Count > 0;
            }
        }
    
        #endregion
    
        #region Public
    
        public void SetError(string propertyName, string errorMessage)
        {
            _errors[propertyName] = errorMessage;
            this.OnPropertyChanged(propertyName);
        }
    
        #endregion
    
        #region Protected
    
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        protected void ClearError(string propertyName)
        {
            this._errors.Remove(propertyName);
        }
    
        protected void ClearAllErrors()
        {
            List<string> properties = new List<string>();
    
            foreach (KeyValuePair<string, string> error in this._errors)
                properties.Add(error.Key);
    
            this._errors.Clear();
    
            foreach (string property in properties)
                this.OnPropertyChanged(property);
        }
    
        #endregion
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
    
        #region IDataErrorInfo Members
    
        public string Error
        {
            get { return null; }
        }
    
        public string this[string columnName]
        {
            get
            {
                if (this._errors.ContainsKey(columnName))
                {
                    return this._errors[columnName];
                }
                return string.Empty;
            }
        }
    
        #endregion
    }

Creating the Book Model Class

This section shows how to create the Book model class that represents the book data entity. To simplify the process this walkthrough will use xml file as data source.

You can get the xml file from: [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Data\BookDataSource.xml

BookDataSource.xml
Copy Code
<?xml version="1.0" encoding="utf-8" ?>
<Books>
    <Book>
        <ID>01583</ID>
        <Image>Application_and_Software_1.jpg</Image>
        <Title>Excel 2007 For Dummies</Title>
        <Author>Greg Harvey, PhD</Author>
        <Category>Computing and Internet</Category>
        <Price>15.83</Price>
    </Book>

    ...

</Books>

Next, you need to add this xml file into your project along with some images for each book.

To add the data file

  1. In your project, create new folder with name Data.
  2. In Data folder, insert the data source from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Data\BookDataSource.xml.
  3. Click on the BookDataSource.xml file and press F4 to open the Property Window. Change the Build Action property to Resources

To add the resources file

  1. In your project, create new folder with name Assets.
  2. In Assets folder, create new folder with name Images.
  3. In Images folder, create new folder with name Books.
  4. In Books folder, copy the images from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Images\Photos\].
    These images will be used as photo for each book in our data source.

Next, you create the Book model class based on the data structure specified in our source file.

To create the Book Model class

  1. In your project, locate Models folder.
    If you do not have this folder, most likely you are using project template that does not have MVVM template ready. See the Preparing Project Environment section above before proceeding to the next step.
  2. In Models folder, add new class with name Book.
  3. At the Book class, inherit the ModelBase class.
    C#
    Copy Code
    public class Book : ModelBase
    {
    }
  4. In Book class, create ID property by defining the backing field along with complete getter and setter in the property. You also need to call the OnPropertyChanged method after the backing field is assigned to notify the binding engine that value has been updated.
    CS
    Copy Code
    private string _id = string.Empty;
    
    public string Id
    {
        get
        {
            return this._id;
        }
    
        set
        {
            if (this._id!= value)
            {
                this._id= value;
                this.OnPropertyChanged("Id");
            }
        }
    }
  5. Create Image, Title, Author, Category and  Price properties by repeating step number 4.
    C#
    Copy Code
    private string _image;
    private string _title;
    private string _author;
    private string _category;
    private decimal _price;
    
    public string Image
    {
        get { return _image; }
        set
        {
            if (this._image != value) {
                _image = value;
                OnPropertyChanged("Image");                
            }
        }
    }
    
    public string Title
    {
        get { return _title; }
        set
        {
            if (this._title != value) {
                _title = value;
                OnPropertyChanged("Title");                
            }
        }
    }
    
    public string Author
    {
        get { return _author; }
        set
        {
            if (this._author != value) {
                _author = value;
                OnPropertyChanged("Author");
            }
        }
    }
    
    public string Category
    {
        get { return _category; }
        set
        {
            if (this._category != value) {
                _category = value;
                OnPropertyChanged("Category");                
            }
        }
    }
    
    public decimal Price
    {
        get { return _price; }
        set
        {
            if (this._price != value) {
                _price = value;
                OnPropertyChanged("Price");
            }
        }
    }
  6. In Book class, create a constructor that accepts XElement as its parameter. This constructor is used to ease the data parsing process from the xml to the object model.
    C#
    Copy Code
    public Book() 
    { 
    }
    
    public Book(XElement x)
    {
        this._id = x.Element("ID").Value.Trim();
        this._image = x.Element("Image").Value.Trim();
        this._title = x.Element("Title").Value.Trim();
        this._author = x.Element("Author").Value.Trim();
        this._category = x.Element("Category").Value.Trim();
        this._price = decimal.Parse(x.Element("Price").Value);
    }

 

Conclusion

In this walkthrough, you have learned how to do the following:

Complete Code Listing

This section lists the complete code used in this walkthrough.

Book.cs

C#
Copy Code
    public class Book : ModelBase
    {
        #region Constructors

        public Book()
        {
        }

        public Book(XElement x)
            : this()
        {
            this._author = x.Element("Author").Value.Trim();
            this._title = x.Element("Title").Value.Trim();
            this._category = x.Element("Category").Value.Trim();
            this._ID = x.Element("ID").Value.Trim();
            this._price = double.Parse(x.Element("Price").Value.Trim());
            this._image = new Uri("/Intersoft.ClientUI.Samples.Assets;component/Images/Books/" + x.Element("Image").Value.Trim() , UriKind.RelativeOrAbsolute);
        }

        #endregion

        #region Fields

        private Uri _image = null;
        private string _author;
        private string _title;
        private string _category;
        private string _ID;
        private double _price;

        #endregion

        #region Properties

        public bool EnableValidation { get; set; }

        public string Author
        {
            get
            {
                return _author;
            }
            set
            {
                if (_author != value)
                {
                    _author = value;
                    ClearError("Author");
                    OnPropertyChanged("Author");
                }
            }
        }

        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                if (_title != value)
                {
                    _title = value;
                    ClearError("Title");

                    if (EnableValidation && string.IsNullOrEmpty(this.Title))
                        SetError("Title", "Title is required");

                    OnPropertyChanged("Title");
                }
            }
        }

        public string Category
        {
            get
            {
                return _category;
            }
            set
            {
                if (_category != value)
                {
                    _category = value;
                    OnPropertyChanged("Category");
                }
            }
        }

        public string ID
        {
            get
            {
                return _ID;
            }
            set
            {
                if (_ID != value)
                {
                    _ID = value;
                    OnPropertyChanged("ID");
                }
            }
        }

        public double Price
        {
            get
            {
                return _price;
            }
            set
            {
                if (_price != value)
                {
                    _price = value;
                    ClearError("Price");

                    if (EnableValidation && (double.IsNaN(this.Price) || this.Price == 0.0))
                        SetError("Price", "Price is required");

                    OnPropertyChanged("Price");
                }
            }
        }

        public Uri Image
        {
            get
            {
                return _image;
            }
            set
            {
                if (_image != value)
                {
                    _image = value;
                    OnPropertyChanged("Image");
                }
            }
        }

        #endregion
    }
See Also

Concepts

Other Resources