Silverlight XamPivotGrid ビューのシリアル化

0 ユーザーが評価
この投稿には確認済みの回答があります。 0 返信 | 1 サポーター

トップ 10 投稿者 
女性
投稿 18
IG Employee
[IG] Yoshimi 投稿済み: 2011/7/10 23:52

元記事 (英語) : Atanas Dyulgerov http://community.infragistics.com/blogs/atanas_dyulgerov/archive/2010/07/15/serializing-xampivotgrid-views-in-silverlight.aspx

XamPivotGrid コントロールは、対話型 (インタラクティブ) ツールです。 ユーザーの設定に従ってデータの変更を視覚化します。データは通常ランタイムで変更されます。 データから探している情報を見つけるには、スライス アンド ダイスやドリルダウンなどのアクションが必要になります。XamPivotGrid では、ユーザーがこれらのアクションを実行できますが、ビューが変更されるだけでデータは変更されずに維持されます。 列としての複数のディメンション階層と行としての階層、フィルターによって定義された特定のビューに戻りたい場合がありますが、手動で条件を設定するのは大変な作業です。どのようにビューを保存し、どのように復元するのでしょう?

この記事ではその質問にお答えします。ピボット グリッド スライスの詳細を シリアル化 せずにメモリに保存します。これはデータを XML ファイル (XML シリアル化) またはデータベース (バイナリ シリアル化) へ永続化する処理の基本的な手順です。

実装について説明する前に、この記事の流れについて少し説明します。 最初の重要なステップとして、ピボット グリッドのビューを再現するために何を保存する必要があるかを把握しておく必要があります。

保存する項目

DataSource にはすべてのデータが含まれます。 XamPivotGrid は DataSource のデータを視覚化するコントロールです。 XamPivotDataSelector は作成したいスライスの設定の選択を助けるコントロール。 現在のビューを保存するために DataSource の設定を変更する必要があります。 以下はスライスを定義する要素です。

  • データ ソースのデータ キューブ
    • コードまたはデータ セレクターで選択
  • 選択されたキューブのディメンション階層
    • 行、列、フィルター (Slicer) の軸へ割り当てます
  • 選択されたキューブのメジャー
    • メジャー領域に割り当て
  • 各選択済みの階層内のメンバーをフィルター
    • フィルター メニューの選択状態
    • ヘッダー セル領域の展開状態

ピボット グリッドのビューを再作成する場合、すべての要素の詳細を保存する必要があります。DataSources のすべてのタイプに有効ですが、必ずしも十分であるとは限りません。FlatDataSource を使用する場合は、保存するのはそれだけです。 XMLADataSource などを使用している場合は、ServerURI とデータベース名を保存する必要があります。保存したビューを読み込む前に、同じ DataSource を使用していることを確認する必要があります。

スライスを再生成するために保存する項目が分かったら、識別情報を保存する場所が必要です。

保存方法:

上記で説明した各要素には UniqueName があります。これは文字列で、ビューを再度読み込む際に対応する要素をデータ内で見つけて、UniqueName を使用して適切な場所に割り当てます。この方法は、保存情報が小さいためビューを保存する最も実用的なアプローチで、簡単にシリアル化することができます。詳細については後ほど説明します。

選択した階層およびキューブの保存は、コレクションに UniqueName 文字列を保存して SelectedIndex 整数を int 変数に保存するたけです。展開および選択された状態はペアで保存しておく必要があります。状態のブール値および値が対応する UniqueName 文字列です。2 つのプロパティを持つカスタム クラスを作成できます。クラスをシリアル化可能にするためにコンストラクタを提供する必要があります。 このサンプルのクラス名は CustomDictItem です。

プロパティと変数のあるすべてのコレクションとプロパティは他のカスタム クラスに保存できます。保存、更新日時など他の便利な情報を保存した各特定のビューに追加できます。参照しているクラスは SavedPivotGridView でサンプルに含まれています。1 つのクラスの保存にすべてのデータを保存するベネフィットは、保存にメソッドを追加できること、そして特定のビューを読み込むことができることです。コードはきれいに体系化され、そのクラスの別のインスタンスのみをシリアル化します。この記事ではその方法について紹介します。

以下はすべての便利な情報を一度に保存するプロパティのスニペットです。

    public class SavedPivotGridView
    {
        #region SavedInformation
 
        private stringtimestamp;
        public stringTimestamp
        {
            get { returntimestamp; }
            set { timestamp = value;}
        }
 
        public intSelectedCubeIndex;
 
        //保存される各行、列、フィルター、メジャーの一意な名前
        public List<string> RowHierarchies;
        public List<string> ColumnHierarchies;
        public List<string> FilterHierarchies;
        public List<string> Measures;
 
        //保存する各メンバーの一意な名前とその IsExpandedproperty
        public List<CustomDictItem> FilterMembersToExpand;
        //保存する各メンバーの一意な名前とその IsSelectedproperty
        public List<CustomDictItem> FilterMembersToLoad;

        #endregion SavedInformation
    }

注: すべてのプロパティがパブリックなため、後でシリアル化できます:

    public class CustomDictItem
    {
        public string UniqueName;
        public bool Value;
 
        //このクラスでシリアル化を有効にするにはパラメーター コンストラクターが必要です
        public CustomDictItem()
        {
 
        }
 
        public CustomDictItem(string UniqueName, bool Value)
        {
            this.UniqueName = UniqueName;
            this.Value = Value;
        }
    }

保存ビューのメソッド

保存したデータを保持するためのプロパティを準備したら、さっそく生成してみましょう。簡単なアプローチとしては、XamPivotGrid を取得するパブリック メソッド SaveView を作成する方法があります。

SavedPivotGridView.cs ファイルの SaveMethods エリアにすべてのコードがあります。どちらかの項目が null の場合、メソッドを中止します。null の場合は、読み込んだデータがないので保存するデータがないことを意味します。

サニティ チェックが終わった後に、選択したキューブを保存します。DataSource が提供するすべてのキューブを使用できます。選択したキューブを修復するには、Cubes プロパティのインデックスのみ必要になります。

            this.SelectedCubeIndex =
                        pivotGrid.DataSource.Cubes.IndexOf(pivotGrid.DataSource.Cube); 

これはキューブに十分です。すべての読み込みディメンション階層型を保存します。階層型データの 3 つの軸があり、Rows、Columns、Filters と呼ばれます。

各軸は実際には IAreaItemViewModel 項目 (選択された階層) のコレクションです。すべてのコレクションを移動し、各 UniqueNames を階層コレクションへ以下のように追加します。

            this.RowHierarchies = new List<string>();
            foreach (IAreaItemViewModel item in pivotGrid.DataSource.Rows)
            {
                var FilterViewModel = item as IFilterViewModel;
                if (FilterViewModel != null)
                {
                    this.RowHierarchies.Add(FilterViewModel.Hierarchy.UniqueName);
                }
            }

pivotGrid.DataSource.Columns および pivotGrid.DataSource.Filters も同様に処理します。

メジャーも同様ですが、IFilterViewModel の代わりに IMeasureViewModel を使用します。

            this.Measures = new List<string>();
            foreach (IAreaItemViewModel item in pivotGrid.DataSource.Measures)
            {
                var measureViewModel = item as IMeasureViewModel;
                if (measureViewModel != null)
                {
                    this.Measures.Add(measureViewModel.Measure.UniqueName);
                }
            }

階層、およびフィルター メンバーの IsExpanded 状態と IsSelected 状態を保存できる Measures を保存します。

フィルター メンバーとは何でしょう?XamPivotGrid UI の階層のフィルター ボタンを選択するときに、階層レベルを表すツリー型のメニューが開きます。 各項目は選択または展開することができます。すでにお分かりかもしれませんが、これがフィルター メンバーです。 HeaderCells の展開インジケーターをクリックするときに、これらのレベルの展開を自動的に実行できます。 HeaderCells からの値の取得も簡単です。

すべてのフィルター メンバーの状態を保存する最良の方法は、反復メソッドを書いてすべてのフィルター メンバーにアクセスすることです。以下のコードは、フィルター階層で展開する必要のあるすべてのメンバーを取得します。

            foreach (IFilterViewModel filterViewModel in pivotGrid.DataSource.Filters)
            {
                if (filterViewModel.FilterMembers != null)
                    foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                        SaveExpansionStateOfFilterMembers(filterMember);
            }

        //フィルター メンバーの展開状態を保存する再帰メソッド
        private void SaveExpansionStateOfFilterMembers(IFilterMember filterMember)
        {
            if (filterMember.FilterMembers != null)
            {
                foreach (IFilterMember subFilterMember in filterMember.FilterMembers)
                {
                    SaveExpansionStateOfFilterMembers(subFilterMember);
                }
            }
 
            CustomDictItem item = new CustomDictItem(filterMember.Member.UniqueName, filterMember.IsExpanded);
 
            if (!CustomDictContains(this.FilterMembersToExpand, item.UniqueName))
            {
                this.FilterMembersToExpand.Add(item);
            }
            else
            {
                GetCustomDictItem(this.FilterMembersToExpand, item.UniqueName).Value = true;
            }
        }

行や列にフィルター メンバーを保存する場合、ショートカットを取得して VisibleColumnsHeaderCells および VisibleRowsHeaderCells コレクションを使用できます。

            foreach (PivotHeaderCell cell in pivotGrid.GridLayout.RowHeaderCells)
            {
                CustomDictItem item = new CustomDictItem(cell.Member.UniqueName, cell.IsExpanded);
 
                if (!CustomDictContains(this.FilterMembersToExpand, item.UniqueName))
                {
                    this.FilterMembersToExpand.Add(item);
                }
                else
                {
                    GetCustomDictItem(this.FilterMembersToExpand, item.UniqueName).Value = true;
                }
            }
            foreach (PivotHeaderCell cell in pivotGrid.GridLayout.ColumnHeaderCells)
            {
                CustomDictItem item = new CustomDictItem(cell.Member.UniqueName, cell.IsExpanded);
 
                if (!CustomDictContains(this.FilterMembersToExpand, item.UniqueName))
                {
                    this.FilterMembersToExpand.Add(item);
                }
                else
                {
                    GetCustomDictItem(this.FilterMembersToExpand, item.UniqueName).Value = true;
                }
            }

注: 同じ UniqueName の項目を追加したかどうかをチェックします。項目が展開される場合、すべての項目がグループに追加されます。項目が同じ UniqueName を持つ実装であるため、展開状態を true に設定する必要があります。

この 3 サイクルによって、読み込み時にフィルター メンバーを展開するために必要なすべての情報が保存されました。IsSelected ステートを保存します。プロセスは似ていますが、今回はショートカットを使用できません。また 3 つのサイクルを再帰的に移動する必要があります。

Columns および Rows のすべての要素が IFilterViewModel タイプではないということです。 1 つ以上の Measure がある場合、コレクションは を IMeasureViewModel 含むため、foreach サイクルを使用できません。

            FilterMembersToLoad = new List<CustomDictItem>();
            for (int i = 0; i < pivotGrid.DataSource.Columns.Count; i++)
            {
                IFilterViewModel filterViewModel = pivotGrid.DataSource.Columns[ i ] as IFilterViewModel;
 
                if (filterViewModel != null)
                {
                    if (filterViewModel.FilterMembers != null)
                        foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                            SaveSelectionStateOfFilterMembers(filterMember);
                }
            }
            for (int i = 0; i < pivotGrid.DataSource.Rows.Count; i++)
            {
                IFilterViewModel filterViewModel = pivotGrid.DataSource.Rows[ i ] as IFilterViewModel;
 
                if (filterViewModel != null)
                {
                    if (filterViewModel.FilterMembers != null)
                        foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                            SaveSelectionStateOfFilterMembers(filterMember);
                }
            }
            foreach (IFilterViewModel filterViewModel in pivotGrid.DataSource.Filters)
            {
                if (filterViewModel.FilterMembers != null)
                    foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                        SaveSelectionStateOfFilterMembers(filterMember);
            }
 
        //フィルター メンバーの選択状態を保存する再帰メソッド
        private void SaveSelectionStateOfFilterMembers(IFilterMember filterMember)
        {
            if (filterMember.FilterMembers != null)
            {
                foreach (IFilterMember subFilterMember in filterMember.FilterMembers)
                {
                    SaveSelectionStateOfFilterMembers(subFilterMember);
                }
            }
 
            if (filterMember.IsSelected.HasValue)
            {
                CustomDictItem item = new CustomDictItem(filterMember.Member.UniqueName, filterMember.IsSelected.Value);
 
                if (!CustomDictContains(this.FilterMembersToLoad, item.UniqueName))
                {
                    this.FilterMembersToLoad.Add(item);
                }
                else
                {
                    GetCustomDictItem(this.FilterMembersToLoad, item.UniqueName).Value = true;
                }
            }
        }

選択した階層 (展開状態およびフィルター選択状態) を各軸に保存しました。 これらはすべて、ピボット グリッドでビューを再構築するための基本的な情報です。

 


保存日時など追加情報が追加できるようになりました。

        this.Timestamp = DateTime.Now.ToString();

ユーザーにこのビューの名前を入力させる他のオプションがあります。 SaveView メソッドをさらにカスタマイズするかどうかは自由です。

fill メソッド

保存したビューを読み込みます。 最適の方法は、パラメーターとしてピボット グリッドのインスタンスを許可するメソッドを提供することです。メソッドは保存した情報を読み込み、XamPivotGrid インスタンスで復元します。

復元プロセスは簡単だと思われるかもしれませんが、そうでもありません。 2 か所注意が必要な場所があります。
以下の段落でご説明しますので、是非ご一読ください。

XamPivotGrid のすべてのデータを読み込むは非同期なため、トリックが必要になります。 読み込み処理の最初でレイアウトを遅延で更新し、処理の終了時にオフにできる理由です。 これにより、すべての変更が一度に実行されます。 フラグを使用して読み込み状態を未完了にマークすることも可能です。 行、列、フィルター、およびメジャーを追加した後は、フィルター メンバーの展開および選択は、データが読み込まれるのを待つ必要があります。 データが読み込まれるときは、イベントにサブスクライブする必要があります。 このイベントは 1 回以上スローされる場合があるためフラグが必要になります。 完全なコードは、サンプルを参照してください。

ビューを読み込む手順として、まずデータの右キューブを選択します。DataSource の Cubes プロパティからのキューブのインデックスを保存し、それを取り出して Cube プロパティに割り当てます。

            pivotGrid.DataSource.Cube =
                        pivotGrid.DataSource.Cubes[this.SelectedCubeIndex];

保存した階層の UniqueName を持つ各ディメンションの階層を見つけて保存した項目を追加する前に、読み込んだ階層をすべてをクリアし、メジャーする必要があります。メジャーも同様です。

            pivotGrid.DataSource.Rows.Clear();
            pivotGrid.DataSource.Columns.Clear();
            pivotGrid.DataSource.Measures.Clear();
            pivotGrid.DataSource.Filters.Clear();

 
各キューブは Dimensions のコレクションを持ち、各 Demension は 階層のコレクションを持ちます。

            foreach (IDimension dim in pivotGrid.DataSource.Cube.Dimensions)
            {
                foreach (IHierarchy hierarchy in dim.Hierarchies)
                {
                    if (this.RowHierarchies.Contains(hierarchy.UniqueName))
                    {
                        IFilterViewModel fvm = pivotGrid.DataSource.CreateFilterViewModel(hierarchy);
                        pivotGrid.DataSource.Rows.Add(fvm);
                    }
                    else if (this.ColumnHierarchies.Contains(hierarchy.UniqueName))
                    {
                        IFilterViewModel fvm = pivotGrid.DataSource.CreateFilterViewModel(hierarchy);
                        pivotGrid.DataSource.Columns.Add(fvm);
                    }
                    else if (this.FilterHierarchies.Contains(hierarchy.UniqueName))
                    {
                        IFilterViewModel fvm = pivotGrid.DataSource.CreateFilterViewModel(hierarchy);
                        pivotGrid.DataSource.Filters.Add(fvm);
                    }
                }
            }

各 Cube は Measure のコレクションを持ちます。

            foreach (IMeasure measure in pivotGrid.DataSource.Cube.Measures)
            {
                if (this.Measures.Contains(measure.UniqueName))
                {
                    IMeasureViewModel mvm = pivotGrid.DataSource.CreateMeasureViewModel(measure);
                    pivotGrid.DataSource.Measures.Add(mvm);
                }
            }

UI の更新をトリガーし、データが読み込まれるのを待つ必要があります。 これは Deferred Layout Update を false に設定し、LayoutLoaded イベントを true に設定します。 サンプル ソースを参照してください。.

データが使用可能な場合、すべてのフィルター メンバーを移動して状態を復元する必要があります。 選択する前にまず展開する必要があります。選択する必要のあるメンバーの親が展開されない場合、ビジュアル ツリーの一部ではなくなるため、メンバーを操作できません。

展開は非同期アクションであるため、ExpandMembers 再帰メソッドで ManualResetEvent を使用する必要があります。以下はそのコードです。

                //列、行、およびフィルターのメンバーを展開します
                for (int i = 0; i < (sender as XamPivotGrid).DataSource.Rows.Count; i++)
                {
                    IFilterViewModel filterViewModel = (sender as XamPivotGrid).DataSource.Rows[ i ] as IFilterViewModel;
 
                    if (filterViewModel != null)
                    {
                        if (filterViewModel.FilterMembers != null)
                            foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                                ExpandMembers(filterViewModel, filterMember);
                    }
                }
                for (int i = 0; i < (sender as XamPivotGrid).DataSource.Columns.Count; i++)
                {
                    IFilterViewModel filterViewModel = (sender as XamPivotGrid).DataSource.Columns[ i ] as IFilterViewModel;
 
                    if (filterViewModel != null)
                    {
                        if (filterViewModel.FilterMembers != null)
                            foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                                ExpandMembers(filterViewModel, filterMember);
                    }
                }
                foreach (IFilterViewModel filterViewModel in (sender as XamPivotGrid).DataSource.Filters)
                {
                    if (filterViewModel.FilterMembers != null)
                        foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                            ExpandMembers(filterViewModel, filterMember);
                }

private void ExpandMembers(IFilterViewModel filterViewModel, IFilterMember filterMember)
        {
            //同期するためにこのイベントを使用するかメンバーを非同期に読み込みます
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            filterViewModel.LoadFilterMembersCompleted += (sender1, e1) => manualResetEvent.Set();
 
            if (CustomDictContains(FilterMembersToExpand, filterMember.Member.UniqueName))
                filterMember.IsExpanded = GetCustomDictItem(FilterMembersToExpand, filterMember.Member.UniqueName);
 
            if (!filterMember.IsExpanded)
                return;
 
            manualResetEvent.WaitOne();
 
            foreach (IFilterMember fm in filterMember.FilterMembers)
            {
                ExpandMembers(filterViewModel, fm);
            }
 
        }

最後に、選択したフィルター メンバーを選択必要する必要があります。展開と同じような方法ですが、手動のリセット イベントの必要はなくなります。

                //列、行、およびフィルターのメンバーを選択します
                foreach (IFilterViewModel filterViewModel in (sender as XamPivotGrid).DataSource.Filters)
                {
                    if (filterViewModel.FilterMembers != null)
                        foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                            SelectMembers(filterMember);
                }
                for (int i = 0; i < (sender as XamPivotGrid).DataSource.Rows.Count; i++)
                {
                    IFilterViewModel filterViewModel = (sender as XamPivotGrid).DataSource.Rows[ i ] as IFilterViewModel;
 
                    if (filterViewModel != null)
                    {
                        if (filterViewModel.FilterMembers != null)
                            foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                                SelectMembers(filterMember);
                    }
                }
                for (int i = 0; i < (sender as XamPivotGrid).DataSource.Columns.Count; i++)
                {
                    IFilterViewModel filterViewModel = (sender as XamPivotGrid).DataSource.Columns[ i ] as IFilterViewModel;
 
                    if (filterViewModel != null)
                    {
                        if (filterViewModel.FilterMembers != null)
                            foreach (IFilterMember filterMember in filterViewModel.FilterMembers)
                                SelectMembers(filterMember);
                    }
                }
 
        private void SelectMembers(IFilterMember filterMember)
        {
            if (filterMember.FilterMembers != null)
            {
                foreach (IFilterMember subFilterMember in filterMember.FilterMembers)
                {
                    SelectMembers(subFilterMember);
                }
            }
 
            if (CustomDictContains(FilterMembersToLoad, filterMember.Member.UniqueName))
                filterMember.IsSelected = GetCustomDictItem(FilterMembersToLoad, filterMember.Member.UniqueName);
        }

Save および Load ビュー クラスはこれでほとんど終わりです。 UniqueName によって CustomDictItem を取得する 2 ヘルパー メソッド、および UniqueName のある項目が存在するかどうかのチェッカーを追加するだけです。

        private CustomDictItem GetCustomDictItem(List<CustomDictItem> ListOfItems, string UniqueName)
        {
            foreach (CustomDictItem item in ListOfItems)
            {
                if (item.UniqueName == UniqueName)
                    return item;
            }
            throw new Exception("Dict does not contain this item");
        }
 
        private bool CustomDictContains(List<CustomDictItem> ListOfItems, string UniqueName)
        {
            foreach (CustomDictItem item in ListOfItems)
            {
                if (item.UniqueName == UniqueName)
                    return true;
            }
            return false;
        }

SavedPivotGridView クラスは、コレクションを復元するための 階層の UniqueNames を保存する多数のコレクションがあります。選択した Cube インデックスおよび復元プロセスに必要ない他の情報を保存します。 このクラスには、指定した XamPivotGrid インスタンスの情報を保存するメソッド、および保存した情報に基づいてインスタンスを生成するための fill メソッドがあります。

次にクラスのインスタンスを保存する方法を決定します。 メモリに保存するかシリアル化して XML ファイルまたはデータベースに保存できます。

XML シリアル化

ここまでは SavedPivotGridView クラスについての情報です。次は、メイン ページにフォーカスしましょう。
ボタンが 2 つあると仮定します。SaveViewToXMLFile と LoadViewFromXMLFile です。 保存ボタン イベント ハンドラーは SavedPivotGridView の新しいインスタンスを追加します。 次にインスタンスの SaveView メソッドを実行し、現在のグリッドの完全なビューを取得し、シリアル化できます。

XML シリアル化には、System.Xml.Serialization 名前空間を追加します。 XmlSerializer クラスという名前空間にインスタンスが必要です。 デフォルト コンストラクタは、シリアル化するデータのクラス型 (SavedPivotGridView クラス) を提供する必要があります。 次にファイル データを保存するために使用する MemoryStream が必要になります。  XmlSerializer の Serialize メソッドを呼び出します。 簡単です。 以下のスニペットは、ボタン クリックを保存し、結果を XML へ保存するすべてのイベント ハンドラーを実装する方法です。

        private void saveToXML_Click(object sender, RoutedEventArgs e)
        {
            XMLSerializedView = new SavedPivotGridView();
            XMLSerializedView.SaveView(this.xamPivotGrid);
 
            XmlSerializer serializer = new XmlSerializer(typeof(SavedPivotGridView));
            MemoryStream memoryStream = new MemoryStream();
            serializer.Serialize(memoryStream, XMLSerializedView);
 
            SaveFileDialog saveFileDialog = new SaveFileDialog()
            {
                DefaultExt = "xml",
                Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*",
                FilterIndex = 1
            };
 
            if (saveFileDialog.ShowDialog() == true)
            {
                using (Stream stream = saveFileDialog.OpenFile())
                {
                    byte[] bytes = memoryStream.ToArray();
                    stream.Write(bytes, 0, bytes.Length);
                    stream.Close();
                    memoryStream.Close();
                }
            }
        }

逆の処理も似ています。 選択したファイルの読み取りストリームを作成する必要があります。 メソッドは SavedPivotGridView へキャストする必要のあるオブジェクトを返し、作成した Fill メソッドを呼び出します。

        private void loadFromXML_Click(object sender, RoutedEventArgs e)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(SavedPivotGridView));
 
            OpenFileDialog openFileDialog = new OpenFileDialog()
            {
                Multiselect = false,
                Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*",
                FilterIndex = 1
            };
 
            bool? result = openFileDialog.ShowDialog();
 
            if (result != null && result == true)
            {
                XMLSerializedView = (SavedPivotGridView)serializer.Deserialize(openFileDialog.File.OpenRead());
                XMLSerializedView.Fill(this.xamPivotGrid);
            }
        }

バイナリ シリアル化

バイナリ シリアル化は XML シリアル化と同じ方法で行うことができますが、名前空間は異なります。
名前空間は System.Runtime.Serialization と呼ばれます。 一方シリアル化クラスでは DataContractSerializer と呼ばれます。Serialize/Deserialize メソッドのペアは、WriteObject および ReadObject とも呼ばれます。

bin シリアル化の結果はデータベースに追加するのが便利なバイト配列です。
作成したサンプルは、プライマリ キーとして更新日時の列と byte[] の値列のある 1 つのテーブルを含むデータベースです。

Silverlight は WCF サービスを使用するために必要な直接データベースへアクセスできません。 サービスがすでに作成されていて、2 つの操作コントラクトがあると仮定します。 UploadView と呼ばれ、 2 つのパラメーター (更新日時とバイト配列) を受け取ります。 もう一方は、DownloadView と呼ばれ、保存するためにデータベースを検索する DateTime パラメーターのみを受け取ります。 段落のあとにサービスを実装します。

サービス参照を追加し、バイナリをシリアル化するためにすべてのコードを見ることができる 2 つのメソッドにアクセスがあると仮定します。 以下のコードはデータベースにビューを保存します。

        private void saveViewToDB_Click(object sender, RoutedEventArgs e)
        {
            SavedPivotGridView view = new SavedPivotGridView();
            view.SaveView(this.xamPivotGrid);
 
            DataContractSerializer serializer = new DataContractSerializer(typeof(SavedPivotGridView));
            MemoryStream memoryStream = new MemoryStream();
            serializer.WriteObject(memoryStream, view);
 
            client.UploadViewAsync(DateTime.Parse(view.Timestamp), memoryStream.ToArray());
        }
 
        void client_UploadViewCompleted(object sender, UploadViewCompletedEventArgs e)
        {
            if (e.Result)
            {
                MessageBox.Show("Upload completed successfuly");
            }
            else
                MessageBox.Show("Upload failed");
        }

注: サービス メソッドは、アップロードが成功したかどうかを確認できる非同期で完了イベントにサブスクライブする必要があります。

次は反復処理です。

        private void loadViewFromDB_Click(object sender, RoutedEventArgs e)
        {
            if (this.listOfViews.SelectedItem != null)
                client.DownloadViewAsync(DateTime.Parse(this.listOfViews.SelectedValue.ToString(), System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat));
            else
                MessageBox.Show("Please select the timestamp of the view you want to load");
        }
 
        void client_DownloadViewCompleted(object sender, DownloadViewCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(SavedPivotGridView));
 
                int len = 0;
                while (e.Result[len] > 0)
                    len++;
                MemoryStream memoryStream = new MemoryStream(e.Result, 0, len);
 
                SavedPivotGridView view = serializer.ReadObject(memoryStream) as SavedPivotGridView;
                view.Fill(this.xamPivotGrid);
            }
            else
                MessageBox.Show("Upload failed");
        }

Result が byte 配列なのは、データベースから取得された結果が常に固定の長さを持つためです。保存サイズに関係なく、配列は使用可能なデータの後にゼロで埋められます。配列の本当の長さを確認する必要があり、これらの境界でメモリ ストリームを作成します。 これを作成をしないと Fill メソッドがクラッシュします。

サービスと 2 つの OperationContracts を作成するだけです。

データベース インタラクション WCF サービス

データベースへアクセス、アップロード、バイト配列してからダウンロードする方法がいくつかあります。ADO.NET エンティティデータ モデルを作成してから、Silverlight が有効なサービスを作成しました。

エンティティ モデルを作成する前にする必要のある最初の手順は、使用するデータベースとテーブルを作成することです。設定は自由に選択できますが、バイト配列の列が十分に大きいことがあります。 PivotGridTests および SerializationSamples という名前のテーブルがあります。 テーブルには、DateTime 型の更新日時の列および byte(8000) 型の SavedView 列があります。 エンティティ モデルを追加するウィザードを使用し、このテーブルのみ含むよう選択しました。

モデルが追加された後に新しい Silverllight の使用が可能なサービスを追加できます。これを DatabaseInteraction.svc と呼びます。 サービスにあるキー コンポーネントはプロキシーと操作のコントラクトです。

    public class DatabaseInteraction
    {
        PivotGridTestsEntities proxy;
   
       
        Operation contracts here
       
   
    }

コツは、プロキシーが初期化されてデータベースが存在するかどうかをすべてのコントラクトで確認することです。確認が済んだらデータベースを操作できます。

ビューをアップロードするには、プロキシーの AddToSerializationSamples メソッドを呼び出してから SaveChanges メソッドを呼び出すことです。 ビューをダウンロードするには、更新日時が一致するかどうかすべての SerializationSamples をチェックすることです。 これも LINQ で実行できます。

以下は 2 つのコントラクトのコードです。

        [OperationContract]
        public bool UploadView(DateTime stamp, byte[] viewToSave)
        {
            if (proxy == null)
                proxy = new PivotGridTestsEntities();
 
            if (proxy.DatabaseExists())
            {
                proxy.AddToSerializationSamples(new SerializationSample() { Timestamp = stamp, SavedView = viewToSave });
                proxy.SaveChanges();
                return true;
            }
            return false;
        }
 
        [OperationContract]
        public byte[] DownloadView(DateTime stamp)
        {
            if (proxy == null)
                proxy = new PivotGridTestsEntities();
 
            if (proxy.DatabaseExists())
            {
                foreach (SerializationSample currentSample in proxy.SerializationSamples)
                {
                    if (currentSample.Timestamp == stamp)
                    {
                        return currentSample.SavedView;
                    }
                }
            }
            return null;
        }

まとめ

この記事では XamPivotGrid ビューを完全に再構築する場合に、保存する必要のある DataSource の重要なコンポーネントについてご説明しました。ここでご紹介した簡単にコンポーネントを保存する方法や保存したビューを xml ファイルやデータベースにシリアル化する方法を次の開発にご活用いただければと思います。

このサンプルを実際に実行するにはソリューション (PivotGridSerialization.zip) を使用し、実際にInfragistics アセンブリに参照を追加する必要があります:

  • InfragisticsSL4.Controls.Grids.XamPivotGrid.v10.2.dll
  • InfragisticsSL4.Controls.Menus.XamTree.v10.2.dll
  • InfragisticsSL4.DragDrop.v10.2.dll
  • InfragisticsSL4.Olap.FlatData.v10.2.dll
  • InfragisticsSL4.Olap.v10.2.dll
  • InfragisticsSL4.v10.2.dll

製品をお持ちでない場合、弊社ウェブサイトよりトライアル版をダウンロードできます。 データベースとテーブルに接続するためにエンティティ モデルを再作成する必要があります。 その際、すべてのプロパティ名と設定した名前が一致するすることを確認してください。

ページ 1 / 1 (1 項目) | RSS
Infragistics Japan
インフラジスティックス ジャパン