デスクトップ地図アプリ開発 ~レイヤー リストの作成~

Document created by tomoyasu_fukuiesrij-esridist Employee on Jul 16, 2018Last modified by masanobu_hiranoesrij-esridist on Jul 18, 2018
Version 8Show Document
  • View in full screen mode

「デスクトップ地図アプリ開発」シリーズの第4弾の記事です。

 

 

今回は、第3弾で作成した地図アプリに、レイヤーの一覧を表示する「レイヤー リスト」を追加します。

本記事で紹介する機能のサンプル コードは ESRIジャパン GitHubで公開しています。

 

レイヤー リストの追加

 

アプリの画面に簡易版の「コンテンツ ウィンドウ」を作成し、その中にレイヤー リストを実装します。また、レイヤー リストには凡例とレイヤーの表示・非表示をチェックボックスで切り替える機能も併せて実装します。

 

 

1. MainWindow.xaml に、レイヤーを表示する枠組みを作成します。

TreeView コントロールを使用してレイヤーと凡例が階層で表示されるように実装し、TreeView の中ではレイヤー名を表示するための 「Binding myLayerName」 と凡例表示の画像を表示するための 「Binding mySymbolImage」を設定します。

 

<TreeView Name="ContentsTree">

    <TreeView.Resources>

        <HierarchicalDataTemplate DataType="{x:Type self: myLayerInfo}" ItemsSource="{Binding Members}">

            <StackPanel Orientation="Horizontal">

                <CheckBox Margin="1" IsChecked="{Binding IsChecked}" Click="CheckBox_Click" Tag="{Binding myLayerID}">

                    <TextBlock Text="{Binding myLayerName}" />

                </CheckBox>

            </StackPanel>

        </HierarchicalDataTemplate>

        <DataTemplate DataType="{x:Type self: mySymbolInfo}">

            <StackPanel Orientation="Horizontal">

                <Image Source="{Binding mySymbolImage}" Margin="0,0,5,0" />

                <TextBlock Text="{Binding mySymbolName}" />

            </StackPanel>

        </DataTemplate>

    </TreeView.Resources>

</TreeView>

 

2. MainWindows.xaml.cs を実装します。初めに、今回使用する以下の名前空間を追加します。

 

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.CompilerServices;

 

3. レイヤー情報を保持するクラスを作成して、バインディングするプロパティを設定します。

次のサンプルでは手順 1 で定義したレイヤー リストに表示するためのレイヤーの名称とシンボルの情報をバインドするクラスを定義しています。

 

// コンテンツ ウィンドウに表示するレイヤーの DataContext プロパティ
public class myLayerInfo: BindableBase
{
    public myLayerInfo ()
    {
        this.Members = new ObservableCollection<mySymbolInfo>();
    }

    public string myLayerName { get; set; }

    public string myLayerID { get; set; }

    public ObservableCollection<mySymbolInfo> Members { get; set; }

    private bool _IsChecked = true;

    public bool IsChecked
    {
        get { return _IsChecked; }
        set { this.SetProperty(ref _IsChecked, value); }
    }

}


// コンテンツ ウィンドウに表示するシンボル画面の DataContext プロパティ
public class mySymbolInfo
{
    public BitmapFrame mySymbolImage { get; set; }

    public string mySymbolName { get; set; }
}


public class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null)
    {
        if (Equals(field, value)) { return false; }

        field = value;

        var h = this.PropertyChanged;

        if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); }

        return true;
    }
}

 

4. 次に、マップに追加されているレイヤーの情報を取得します。

サンプルではマップ オブジェクトからレイヤー オブジェクトリストを取得して、そこからレイヤーの名称、シンボルの情報を取得しています。取得した情報をもとにレイヤー情報を格納する myLayerInfo オブジェクトのリストを新たに作成し、前の手順で作成した TreeView にバインドします。

 

public async void TreeViewMultipleTemplatesSample()
{
    long i = 0;

    // TreeView にバインドする値を保持するためのレイヤー情報を格納する myLayerInfo の List オブジェクトを定義する

    List<myLayerInfo> layers = new List<myLayerInfo>();

    // マップに追加されているレイヤーの一覧を取得
    foreach(var mylayer in MyMapView.Map.AllLayers)
    {
        // マップに格納されているレイヤーにユニークな ID を設定 (レイヤーの表示・非表示機能を実装する際に使用する)
        mylayer.Id = i.ToString();

        // レイヤー名 (レイヤー オブジェクトから取得) とレイヤー ID をセットして myLayerInfo オブジェクトを作成する
        myLayerInfo myLayerInfo = new myLayerInfo() { myLayerName = mylayer.Name, myLayerID = mylayer.Id };


        // レイヤーに設定されているシンボル情報 (シンボル画像とその名称) を取得する
        var legendinfos = await mylayer.GetLegendInfosAsync();

        if (legendinfos != null)
        {
            foreach(var item in legendinfos)
            {
                // シンボルを BitmapFrame 型に変換し画像として取得する
                var sym = item.Symbol;

                var imageData = await sym.CreateSwatchAsync(1 * 96);

                var imgst = await imageData.GetEncodedBufferAsync();

                var img = System.Drawing.Bitmap.FromStream(imgst);

                // メモリストリームに BitmapFrame を保存して myLayerInfo オブジェクトにシンボルの画像と名称をセットする
                using (Stream stream = new MemoryStream())
                {
                    img.Save(stream, ImageFormat.Png);

                    stream.Seek(0, SeekOrigin.Begin);

                    myLayerInfo.Members.Insert(0, new mySymbolInfo() { mySymbolImage = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad), mySymbolName = item.Name });
                }
            }
        }
        // List オブジェクトの一番上に myLayerInfo を追加する
        layers.Insert(0, myLayerInfo);

        i = i + 1;
    }
    // 作成した List オブジェクトの値を TreeView に反映する
    ContentsTree.ItemsSource = layers;
}

 

Tips:

レイヤーの名称は Map クラスが持つ AllLayers プロパティを使用することで取得でき、シンボルの情報は Layer クラスが持つ GetLegendInfosAsync() メソッドで取得できます。サンプルで使用している主題図用のレイヤーは、土地利用の種別によって異なるシンボルが設定されています。 GetLegendInfosAsync() ではレイヤーに設定されている各シンボルとその名称のセットが返されます。

 

5. 次に、アプリケーションを起動したときにレイヤー リストを作成するためのイベント呼び出し処理を記述します。

Initialize メソッドの最後に手順 4 で定義したメソッドの呼び出しを追記します。

 

public async void Initialize()
{
    // 中略


    // マップに追加されているレイヤーの一覧取得
    TreeViewMultipleTemplatesSample();
}

 

ここまでで、レイヤーの一覧を取得してレイヤー リストを作成する実装ができました。

 

 

6. 次に、レイヤー リストに表示しているチェックボックスにレイヤーの表示・非表示を切り替える機能を実装します。

MainWindows.xaml.cs にチェックボックスのイベントハンドラーを実装します。

 

// コンテンツ ウィンドウのチェックボックスのイベントハンドラー
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
        var checkBox = (CheckBox)sender;


        // レイヤーの表示・非表示を切り替える
        visivleLayer(checkBox.Tag.ToString());
}

 

 

7. 続いて、チェックボックスのイベントハンドラーの中で呼び出しを行う、visivleLayer メソッドを定義します。

メソッドの中では、チェックボックスの tag プロパティに格納したレイヤー ID とマップ オブジェクトに格納されているレイヤーの ID(手順 4 で設定) を比較し、 ID が一致したレイヤーの表示・非表示を切り替えます。

 

// レイヤーの表示・非表示
private void visivleLayer(string layername)
{
    foreach (var mylayer in MyMapView.Map.AllLayers)
    {
        if (mylayer.Id == layername)
        {
            if (mylayer.IsVisible)
            {
                // レイヤーを非表示にする
                mylayer.IsVisible = false;
            }
            else
            {
                // レイヤーを表示する
                mylayer.IsVisible = true;
            }
        }
    }
}

 

 

Tips:

レイヤーの表示・非表示は、Layer クラスが持つ IsVisible プロパティを使って切り替えを行います。

※マップの作成方法によりデフォルトではレイヤー ID を保有していないレイヤーも存在するため、手順 4 で新たにレイヤーにユニークな ID を設定してレイヤーの識別を行っています。

 

アプリケーションを実行してレイヤーの表示・非表示を切り替えてみます。

 

 

第4弾「レイヤー リストの作成」ではマップに含まれるレイヤーの一覧を表示するレイヤー リストの作成方法をご紹介しました。次回の第5弾では、開発したアプリケーションを配布するために必要な ArcGIS Runtime SDK の「ライセンス認証方法」をご紹介する予定です。

 

関連リンク

1 person found this helpful

Attachments

    Outcomes