SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Silverlightで行うデータ処理アプリケーション開発の第一歩

Silverlightが持つ強力なデータバインド機能

Silverlightで行うデータ処理アプリケーション開発の第一歩 第4回

 では次に、エンティティクラス=商品詳細情報クラス(ProductDetailContainer)のコードを確認してみましょう。ちょっと長いですが頑張ってみてください。

リスト ProductDetailContainer.cs
public class ProductDetailContainer : INotifyPropertyChanged
{
    private string productImageUrl;
    private Products product;
    private ProductColors productColor;
    private IEnumerable<ProductColors> productColors;

    public event PropertyChangedEventHandler PropertyChanged;

    public IEnumerable<ProductColors> ProductColors
    {
        get { return this.productColors; }
        set
        {
            if (this.productColors != value)
            {
                this.productColors = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ProductColors"));
                this.ProductColor = productColors.FirstOrDefault(color => color.ProductColorId == product.DefaultColorId);
            }
        }
    }
     
    public Products Product
    {
        get { return this.product; }
        set
        {
            if (this.product != value)
            {
                this.product = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Product"));
            }
        }
    }

    public ProductColors ProductColor
    {
        get { return this.productColor; }
        set
        {
            if (this.productColor != value)
            {
                this.productColor = value;
                this.ProductImageUrl = productColor.ProductImageUrl;
                PropertyChanged(this, new PropertyChangedEventArgs("ProductColor"));
            }
        }
    }

    public string ProductImageUrl
    {
        get { return this.productImageUrl; }
        set
        {
            if (this.productImageUrl != value)
            {
                this.productImageUrl = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ProductImageUrl"));
            }
        }
    }

}

 このクラスは、4つのメンバーを持っています。string型のProductImageUrl、Products型のProduct、ProductColors型のProductColor、IEnumerable<ProductColors>型のProductColorsです。

 選択された商品の情報は1件であり、それに相当するのがProducts型のProductです。商品には色が複数存在するため、IEnumerable<ProductColors>型のProductColorsは集合型となります。そして、色の選択があると(ListBoxを選択すると)、ProductColors型の ProductColorがセットされ、そのセット中に、string型のProductImageUrlが決定します。各Setterの中で、プロパティの変更通知であるPropertyChangedイベントをコールしているのが分かります。

 エンティティのメンバーが持つイメージを実行画面に当てはめると次のようになります。

エンティティのメンバーが持つイメージ(Product.xaml)
エンティティのメンバーが持つイメージ(Product.xaml)

 最後にProduct.xamlに画面が遷移したタイミングで実行されるコードの一部を紹介します。

リスト Product.xaml.csの一部
private void GetProductDetail()
{
    Guid productId = Guid.Empty;
    if (NavigationContext.QueryString.ContainsKey("id"))
    {
        productId = new Guid(NavigationContext.QueryString["id"]);
    }

    productDetail = new ProductDetailContainer();
    LayoutRoot.DataContext = productDetail;

    MSStoreSampleEntities context = MSStoreSampleEntities.CreateNoTracking();
    var productQuery = (from product in context.Products
                        where product.ProductId == productId
                        select product) as DataServiceQuery<Products>;
    productQuery.BeginExecute(ProductQueryCompleted, productQuery);

    var colorsQuery = (from color in context.ProductColors
                       where color.ProductId == productId
                       select color) as DataServiceQuery<ProductColors>;
    colorsQuery.BeginExecute(ProductColorsQueryCompleted, colorsQuery);
}

 このように、初めにLayoutRoot.DataContextに対して、エンティティであるProductDetailContainerオブジェクト(productDetail)を割り当ててしまいます。このDataContextは、XAML上にある各コントロールの上位に存在するGridパネル(LayoutRoot)なので、その参照(エンティティオブジェクト)は配置された各コントロールのバインドの定義にも使用できます。これにより各データ要素が画面上に表示されます。

 まだ、上記にはコールバックのプロシージャがありませんので、以下に示しておきたいと思います。

リスト Product.xaml.csの一部(コールバック プロシージャ)
private void ProductQueryCompleted(IAsyncResult result)
{
    Dispatcher.BeginInvoke(() =>
    {
        DataServiceQuery<Products> query = result.AsyncState as DataServiceQuery<Products>;
        productDetail.Product = query.EndExecute(result).FirstOrDefault();
    });
}

private void ProductColorsQueryCompleted(IAsyncResult result)
{
    Dispatcher.BeginInvoke(() =>
    {
        DataServiceQuery<ProductColors> query = result.AsyncState as DataServiceQuery<ProductColors>;
        productDetail.ProductColors = query.EndExecute(result).ToList();
    });
}

 実際にデータサービスから取得したデータは、エンティティであるProductDetailContainerオブジェクトのメンバーに参照を渡しています。このように、後からエンティティオブジェクトにデータが追加(変更)された場合においても、INotifyPropertyChangedから提供される機能を実装したエンティティクラスとバインドを行っているため、コントロール側にデータが反映されるというシナリオを実現することが可能です。

 また、商品の色の選択を画面上でユーザーが行った場合(ListBoxの選択を行った場合)、ListBoxのSelectedItemのバインド先はProductColorになっているため(TwoWayバインド)、ProductColorのSetterに選択した値が伝わります。そこでは、ProductImageUrlを新しい値に更新しており、結果として画面にある大きなイメージは選択された色の画像に変更になります。

 こうした形で、エンティティクラスを間に挟むことによって、画面UIの設計に関しても柔軟に考えることができるようになるのが、XAMLベースで構築するプレゼンテーションレイヤーの典型的な考え方です。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Silverlightで行うデータ処理アプリケーション開発の第一歩連載記事一覧

もっと読む

この記事の著者

マイクロソフト株式会社 小高 太郎(コダカ タロウ)

マイクロソフト株式会社 デベロッパーエバンジェリスト。某国内SI企業にてERPパッケージ開発に携わり、プログラマー、SE、PMと様々なロールを担当すると共に、Microsoft Universityの講師を兼務する。マイクロソフト株式会社では、デベロッパーエバンジェリストとして開発者向けに様々な技術...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/5144 2010/05/13 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー