共用方式為


Creating Data Classes

October 21, 2011

Before you can display data in your Windows Phone UI, you typically organize your data into classes.

You Will Learn

  • How to organize your data to create data classes.
  • How to create data classes that update when changes occur.
  • How to create data collections that update when changes occur.

Applies To

  • Silverlight for Windows Phone OS 7.1

    Gg680258.333ccf64-0dbf-4623-a25b-983ee7bb5a5a(en-us,PandP.11).png

Organizing Your Data

You can create data classes in many different ways. For example, in applications that interact with external data sources, you might use data classes generated through the ADO.NET Entity Framework or WCF Data Services. For simple applications, you can use plain old CLR object (POCO) classes that you create by hand. These classes often contain little more than properties to hold your data and a little change-notification code.

Tip

Unless your application is simple and self-contained, and will not be the subject of continued development, it can benefit from a more advanced architecture. This generally means encapsulating additional kinds of code into separate classes or layers in order to minimize the side-effects of future changes, make debugging easier, and support unit testing.

In XAML-based applications, a common pattern to use is the Model-View-ViewModel (MVVM) pattern. Because the Fuel Tracker application is relatively simple, it does not implement the MVVM pattern, and this documentation does not cover the pattern in further detail. For information about how to use MVVM, see Implementing the Model-View-ViewModel Pattern in a Windows Phone Application. For guidance on how to apply the MVVM pattern to larger-scale phone application development, see Patterns and Practices Windows Phone 7 Developer Guide.

Fuel Tracker is a simple application and uses CLR objects for its data model. The following illustration shows the Car, Fillup, and CarDataStore classes for the Fuel Tracker application. There are other classes in the application, but these are the key classes.

Gg680258.ef1cc27d-fc65-4238-b1ab-7571731187a7(en-us,PandP.11).png

The Car class holds information about the user’s car. The Fillup class holds information about each fill-up. All of the Car and Fillup properties represent simple value types except for the Car.FillupHistory property, which is a collection of fill-ups. The CarDataStore class is a static class that contains methods for saving and loading the Car and Fillup data that the UI pages bind to.

Notice that the Car and Fillup classes implement the INotifyPropertyChanged interface. INotifyPropertyChanged is required for most types of data binding to keep the UI up to date. For more information about data binding, see Displaying Data with Data Bindingearlier in this documentation.

Change Notification

Applications use data classes in many different ways, including displaying their values directly, enabling users to change the values, using the values to calculate other values, or to drive UI state changes. In all of these cases, the application must update itself whenever the property values change. For this reason, it is useful for classes to implement change notification.

To provide change notification, your classes must implement the INotifyPropertyChanged interface. Change notification isn't always necessary, but it is required in so many common scenarios that it is useful to implement INotifyPropertyChanged just in case. The implementation is straightforward, as shown in the following code examples from the Car class.

public class Car : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value) return;
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

    // ... other properties ...

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
       var handler = PropertyChanged;
       if (handler != null) 
         handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Public Class Car
    Implements INotifyPropertyChanged

    Private _name As String

    Public Property Name As String
        Get
            Return _name
        End Get
        Set(value As String)
            If _name = value Then Return
            _name = value
            NotifyPropertyChanged("Name")
        End Set
    End Property

    ' ... other properties ...

    Public Event PropertyChanged As PropertyChangedEventHandler _
        Implements INotifyPropertyChanged.PropertyChanged

    Private Sub NotifyPropertyChanged(ByVal propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

End Class

The property setter updates the backing field and raises a change notification only when the property value actually changes. This is useful to avoid unnecessary change notifications.

When you bind objects to your UI, the binding engine subscribes to the object's PropertyChanged event so that it can update all bound controls whenever a property value changes.

Change Notification with Collections

To fully support change notification for a collection, for example when items are added or removed from the collection, the collection must implement the INotifyCollectionChanged interface. ObservableCollection<T> is a dynamic data collection provided by the framework that can hold generic types. ObservableCollection<T> implements both INotifyPropertyChanged and INotifyCollectionChanged, so the easiest way to support change notifications for collections is to just put your items in an ObservableCollection<T>. The items that you put in the ObservableCollection<T> must implement INotifyPropertyChanged if you want change notification for properties of objects in the collection too.

The Fuel Tracker application uses one collection named FillupHistory that contains information about all of the fill-ups. FillupHistory is an ObservableCollection<T> of Fillup objects, as shown in the following code examples from the Car class.

private ObservableCollection<Fillup>_fillupHistory;

public ObservableCollection<Fillup> FillupHistory
{
    get { return _fillupHistory; }
    set
    {
        if (_fillupHistory == value) return;
        _fillupHistory = value;
        if (fillupHistory != null) 
        {
           _fillupHistory.CollectionChanged += delegate
            {
                NotifyPropertyChanged("AverageFuelEfficiency");
                NotifyPropertyChanged("LastFillup");
            };
        }
        NotifyPropertyChanged("FillupHistory");
        NotifyPropertyChanged("AverageFuelEfficiency");
    }
}
Private _fillupHistory As ObservableCollection(Of Fillup)

Public Property FillupHistory As ObservableCollection(Of Fillup)
    Get
        Return _fillupHistory
    End Get
    Set(value As ObservableCollection(Of Fillup))
        If (_fillupHistory Is Nothing AndAlso value Is Nothing) OrElse
            (_fillupHistory IsNot Nothing AndAlso
             _fillupHistory.Equals(value)) Then Return
        _fillupHistory = value
        If _fillupHistory IsNot Nothing Then
            AddHandler _fillupHistory.CollectionChanged,
                Sub() 
                    NotifyPropertyChanged("AverageFuelEfficiency")
                    NotifyPropertyChanged("LastFillup")
                End Sub
        End If
        NotifyPropertyChanged("FillupHistory")
        NotifyPropertyChanged("AverageFuelEfficiency")
    End Set
End Property

This code also demonstrates how to use change notification to affect other properties. Changing the fill-up history or any items within the fill-up history will affect the average fuel efficiency calculation. Therefore, setting the FillupHistory property raises a change notification for itself and for the AverageFuelEfficiency property. Additionally, setting the property attaches a CollectionChanged event handler to the new collection so that it can raise a change notification for AverageFuelEfficiency and LastFillup whenever an item in the collection is added, removed, or changed.

Next Topic | Previous Topic | Home