방법: Windows Phone의 OData 클라이언트 상태 지속

2012-02-09

Windows Phone의 OData(Open Data Protocol) 클라이언트 라이브러리를 사용하는 응용프로그램에서 상태를 유지하려면 DataServiceState 클래스의 인스턴스를 사용해야 합니다. 자세한 내용은 Windows Phone의 OData(Open Data Protocol) 클라이언트를 참조하십시오.

팁팁:

추적된 엔터티 개체를 상태 사전에 직접 저장하려고 하면 직렬화 과정에서 오류가 발생할 수 있습니다. 추적된 개별 개체의 상태를 유지하려면 엔티티의 URI를 대신 저장합니다. TryGetUri(Object, Uri%) 메서드를 호출하여 엔터티 개체의 URI를 얻을 수 있습니다. 나중에 TryGetEntity<(Of <<'(TEntity>)>>)(Uri, TEntity%) 메서드에 저장된 URI를 전달하는 방법으로 복원된 DataServiceContext에서 개체를 검색할 수 있습니다.

이 항목의 예제에서는 OnNavigatingFrom(NavigatingCancelEventArgs) 메서드를 호출할 때 단일 페이지의 데이터 서비스 상태를 페이지 상태 사전에 저장한 다음 OnNavigatedTo(NavigationEventArgs)를 호출할 때 이 데이터를 복원하는 방법을 보여 줍니다. 이 예제는 상태를 유지하기 위해 DataServiceState 클래스를 사용하여 개체를 직렬화하는 방법과 개체를 복원하는 방법의 기본 사항을 보여 줍니다. 하지만 다중 페이지 데이터 응용프로그램에는 MVVM(Model-View-ViewModel) 디자인 패턴을 사용하는 것이 좋습니다. MVVM을 사용하는 경우 데이터가 Deactivated 이벤트 처리기 메서드에서 응용프로그램의 State 사전에 저장되며 Activated 이벤트 처리기에서 복원됩니다. 이 경우 ViewModel이 활성화 및 비활성화를 수행해야 합니다. 자세한 내용은 연습: Windows Phone의 OData(MVVM 포함) 사용을 참조하십시오.

이 항목의 예제에서는 방법: Windows Phone의 OData 서비스 사용에 설명된 단일 페이지 응용프로그램을 확장합니다. 이 응용프로그램은 OData 웹 사이트에 게시된 Northwind 샘플 데이터 서비스를 사용합니다. 이 샘플 데이터 서비스는 읽기 전용이므로 변경 사항을 저장하려고 하면 오류가 반환됩니다.

다음 예제에서는 데이터 서비스 상태를 직렬화하고 페이지 상태 사전에 저장하는 방법을 보여 줍니다. 이 작업은 페이지에 대한 OnNavigatingFrom(NavigatingCancelEventArgs) 메서드에서 수행됩니다.

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
    // Define a dictionary to hold an existing 
    // DataServiceCollection<Customer>. 
    var collections = new Dictionary<string, object>();
    collections.Add("Customers", customers);

    // Serialize the data service data and store it in the page state.      
    this.State["DataServiceState"] =
        DataServiceState.Serialize(context, collections);
}

다음 예제에서는 페이지 상태 사전에서 데이터 서비스 상태를 복원하는 방법을 보여 줍니다. 이 복원 작업은 페이지에 대한 OnNavigatedTo(NavigationEventArgs) 메서드에서 수행됩니다.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    // Get the object data if it is not still loaded.
    if (!this.isDataLoaded)
    {
        object storedState;
        DataServiceState state;

        // Try to get the serialized data service state.
        if (this.State.TryGetValue("DataServiceState", out storedState))
        {
            // Deserialize the DataServiceState object.
            state = DataServiceState.Deserialize(storedState as string);

            // Set the context from the stored object.
            var restoredContext = (NorthwindEntities)state.Context;

            // Set the binding collections from the stored collection.
            var restoredCustomers = state.RootCollections["Customers"]
                as DataServiceCollection<Customer>;

            // Use the returned data to load the page UI.
            this.LoadData(restoredContext, restoredCustomers);
        }
        else
        {
            // If we don't have any data stored, 
            // we need to reload it from the data service.
            this.LoadData();
        }
    }
}

이 예제에서는 먼저 isDataLoaded 변수를 검사하여 데이터가 여전히 메모리에 활성화되어 있는지 확인해야 합니다. 이 상태는 응용프로그램이 유휴 상태이지만 종료되지 않은 경우에 발생할 수 있습니다. 데이터가 메모리에 없는 경우 먼저 상태 사전에서 데이터를 복원하고 저장된 데이터를 사용하여 UI에 바인딩하는 LoadData 메서드 버전을 호출합니다. 데이터가 상태 사전에 저장되어 있지 않으면 데이터 서비스에서 데이터를 가져오는 LoadData 메서드 버전을 호출합니다. 이 작업은 응용프로그램을 처음 실행할 때 수행됩니다.

이 예제에서는 이전 예제에서 호출된 LoadData 메서드 오버로드 두 개를 보여 줍니다.

// Display data from the stored data context and binding collection. 
public void LoadData(NorthwindEntities context, DataServiceCollection<Customer> customers)
{
    this.context = context;
    this.customers = customers;

    this.isDataLoaded = true;
}
private void LoadData()
{
    // Initialize the context and the binding collection. 
    context = new NorthwindEntities(northwindUri);
    customers = new DataServiceCollection<Customer>(context);

    // Define a LINQ query that returns all customers.
    var query = from cust in context.Customers
                select cust;

    // Register for the LoadCompleted event.
    customers.LoadCompleted
        += new EventHandler<LoadCompletedEventArgs>(customers_LoadCompleted);

    // Load the Customers feed by executing the LINQ query.
    customers.LoadAsync(context.Customers);

}
void customers_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
    if (e.Error == null)
    {
        // Handle a paged data feed.
        if (customers.Continuation != null)
        {
            // Automatically load the next page.
            customers.LoadNextPartialSetAsync();
        }
        else
        {
            // Set the data context of the list box control to the sample data.
            this.LayoutRoot.DataContext = customers;

            this.isDataLoaded = true;
        }
    }
    else
    {
        MessageBox.Show(string.Format("An error has occurred: {0}", e.Error.Message));
    }
}

표시: