すぐに使えるWPF/SilverlightのUI開発パターン

Windowsエクスプローラ型アプリケーション

グレープシティ株式会社 八巻 雄哉
2012/01/12
Page1 Page2 Page3

コンテンツ部分の作成

Gridコントロールの配置と設定

 コンテンツ部分のレイアウトとしてGridコントロールを使用する。

ツールボックスからGridコントロールをベース・レイアウトのGridコントロールの2行目にドラッグ&ドロップする。

Gridコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

 Gridコントロールが以下のXAMLコードとなるように3つの列を作成し、設定を行う(先ほどは「行」だったが、ここでは「列」であることに注意)。

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="210" />
    <ColumnDefinition Width="585" />
    <ColumnDefinition Width="229*" />
  </Grid.ColumnDefinitions>
</Grid>
コンテンツ部分のレイアウトとなるGridコントロールの構成
3行目のWidthプロパティは「*」が付いてさえいれば、数字はいくつでも構わない。

[プロパティ]ウィンドウで、GridコントロールのColumnDefinitionsプロパティに表示されている[…]ボタンを押して[コレクション エディター: ColumnDefinitions]ダイアログを表示する。

ダイアログで、1つ目の「ColumnDefinition」を選択し、プロパティを次のように設定する。

プロパティ
MinWidth 58

3つ目の「ColumnDefinition」を選択し、プロパティを次のように設定して、ダイアログの[OK]ボタンをクリックする。

プロパティ
MinWidth 69

TreeViewコントロールの配置と設定

ツールボックスからTreeViewコントロールをGridコントロールの1列目にドラッグ&ドロップする。

TreeViewコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

[プロパティ]ウィンドウで、TreeViewコントロールに対して次のプロパティを設定する。

プロパティ
BorderThickness 0
Margin 0,0,1,0

[プロパティ]ウィンドウで、TreeViewコントロールのItemsプロパティに表示されている[…]ボタンを押して[コレクション エディター: Items]ダイアログを表示する。

ダイアログで、[追加]ボタンをクリックして1つTreeViewItemオブジェクトを追加し、そのプロパティを以下のように設定する。

プロパティ
Header コンピューター
IsExpanded True

さらに、先ほど追加したTreeViewItemオブジェクトのItemsプロパティに表示されている[…]ボタンを押して[コレクション エディター: Items]ダイアログを表示する(=つまりダイアログの上にダイアログが表示される状態になる)。

[追加]ボタンを3回クリックして3つのTreeViewItemオブジェクトを追加し、それぞれのHeaderプロパティを次のように設定する。最後に、ダイアログの[OK]ボタンをクリックして、2つのダイアログを閉じる。

TreeViewItem Headerプロパティの値
1番目 ローカルディスク (C:)
2番目 ローカルディスク (D:)
3番目 ローカルディスク (E:)

2つ目の[コレクションエディター: Items]ダイアログの設定例

XAMLビューで、<TreeView>タグに次の水平方向のスクロールバーを無効にする属性設定(具体的には下記のコード)を追加する。

ScrollViewer.HorizontalScrollBarVisibility="Disabled"
<TreeView>タグに設定する属性のコード(水平方向のスクロールバーを無効にする設定)

ListBoxコントロールの配置と設定

 WPFでWindowsエクスプローラにあるファイル一覧表示のようなUIを実現する場合、ListViewコントロールを使用するのが一般的である。しかしながら、本稿では、Silverlightと共通で説明するためにListBoxコントロールを使った実装とする(SilverlightにListViewコントロールが存在しないため)。

 ListBoxコントロールでは、ListBoxコントロール内の項目1つ1つをListBoxItemオブジェクトで静的に設定することも可能であるが、今回のWindowsエクスプローラの例のように、通常は項目の内容が動的に変化する場合が多い。項目の内容が動的に変化する場合は、データ・バインディングとデータ・テンプレートを使用することになるため、本稿でもデータ・テンプレートを使用したレイアウト方法を紹介する。

 また、WPFの場合ListBoxコントロールのIsSynchronizedWithCurrentItemプロパティを「True」に設定して選択された項目と内部で自動生成されるCollectionViewオブジェクトの現在の項目を同期する方法が存在するが、Silverlightではこの手法は使用できない。そのため、Silverlightと共通で使用できる方法を採用している。なお、データ・バインディング部分については本稿の趣旨から外れるため、詳細については「データの表示と入力に必要な知識 − @IT」を参照してほしい。

データソースの作成とデータ・コンテキストの設定

「File」という名前の新しいクラスをプロジェクトに追加する。

File.vb/File.csファイルに次のコードを記述する。

Public Class File
  Public Property Name As String
  Public Property Type As String
  Public Property Size As String
  Public Property ImageSize As String
  Public Property CreateDate As String
End Class
namespace WindowsExplorerSample
{
  public class File
  {
    public string Name { get; set; }
    public string Type { get; set; }
    public string Size { get; set; }
    public string ImageSize { get; set; }
    public string CreateDate { get; set; }
  }
}
Fileクラスのコード内容(上:VB、下:C#)

「MainViewModel」という名前の新しいクラスをプロジェクトに追加する。

MainViewModel.vb/MainViewModel.csファイルに、次のコードを記述する。

Imports System.Collections.ObjectModel
Imports System.ComponentModel

Public Class MainViewModel
  Implements INotifyPropertyChanged

  Public Sub New()
    Dim files = New ObservableCollection(Of File)()
    For index = 1 To 10
      files.Add(New File() With{.Name = "Image.jpg", .ImageSize = "256 × 256", .Type = "JPEG イメージ", .Size = "256 KB", .CreateDate = "2011/11/11 11:11" })
    Next
    Me.Files = files
    SelectedFile = files(0)
  End Sub

  Public Property Files() As ObservableCollection(Of File)
  Private selectedFileValue As File
  Public Property SelectedFile() As File
    Get
      Return selectedFileValue
    End Get
    Set(ByVal value As File)
      selectedFileValue = value
      NotifyPropertyChanged("SelectedFile")
    End Set
  End Property


#Region "INotifyPropertyChanged"
  Private Sub NotifyPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
  End Sub

  Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
#End Region
End Class
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WindowsExplorerSample
{
  public class MainViewModel : INotifyPropertyChanged
  {
    public MainViewModel()
    {
      ObservableCollection<File> files = new ObservableCollection<File>();
      for (int i = 0; i < 10; i++)
      {
        files.Add(new File() { Name = "Image.jpg", ImageSize = "256 × 256", Type = "JPEG イメージ", Size = "256 KB", CreateDate = "2011/11/11 11:11" });
      }
      Files = files;
      SelectedFile = files[0];
    }

    public ObservableCollection<File> Files { get; set; }
    private File selectedFile;
    public File SelectedFile
    {
      get
      {
        return selectedFile;
      }
      set
      {
        selectedFile = value;
        NotifyPropertyChanged("SelectedFile");
      }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
      }
    }
    #endregion
  }
}
MainViewModelクラスのコード内容(上:VB、下:C#)

任意のJPEG画像ファイルをファイル名「Image.jpg」(サンプル画像のダウンロード)とし、[プロジェクト]メニューの[既存項目の追加]から追加する。

[ビルド]メニューの[ソリューションのビルド]をクリックする。

デザイン時データ・コンテキストの設定

 [プロパティ]ウィンドウから[データ バインディング ビルダー]を使用してデータ・バインディングを設定するために、デザイン時データ・コンテキストを設定する。

MainWindow.xaml/MainPage.xamlファイルをWPF/Silverlightデザイナで開く。

XAMLビューで、最上位のタグ(Window/UserControlコントロール)に属性として、次の名前空間の割り当てとデザイン時データ・コンテキストの設定を追加する。

xmlns:local="clr-namespace:WindowsExplorerSample"
d:DataContext="{d:DesignInstance Type=local:MainViewModel}"
最上位タグに設定する属性のコード(名前空間の割り当てとデザイン時データ・コンテキストの設定)

実行時データ・コンテキストの設定

XAMLビューで、最上位のタグ(Window/UserControlコントロール)に子要素として、次のデータ・コンテキストの設定を追加する。

<Window.DataContext>
  <local:MainViewModel />
</Window.DataContext>
<UserControl.DataContext>
  <local:MainViewModel />
</UserControl.DataContext>
最上位タグに設定する子要素のコード(データ・コンテキストの設定)(上:WPFの場合、下:Silverlightの場合)

ListBoxコントロールのプロパティ設定

ツールボックスからListBoxコントロールをコンテンツ部分のGridコントロールの2列目にドラッグ&ドロップする。

ListBoxコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

[プロパティ]ウィンドウで、ListBoxコントロールに対して次のプロパティを設定する。

プロパティ
BorderThickness 0
Margin 0,0,1,0

[プロパティ]ウィンドウで、ItemsSourceプロパティの値部分をクリックして[データ バインディング ビルダー]を表示し、次のように設定する。

項目
ソース DataContext - MainViewModel
パス Files

[データ バインディング ビルダー]の設定例

[プロパティ]ウィンドウで、SelectedValueプロパティの左の列の端にある[プロパティ マーカー]()をクリックし、メニューを表示する。そのメニューの[データ バインドの適用]をクリックして[データ バインディング ビルダー]を表示し、次のように設定する。

項目
ソース DataContext - MainViewModel
パス SelectedFile
オプション モード:TwoWay

XAMLビューで、<ListBox>タグに次の水平方向のスクロールバーを無効にする属性設定(具体的には次のコード)を追加する。

ScrollViewer.HorizontalScrollBarVisibility="Disabled"
<ListBox>タグに設定する属性のコード(水平方向のスクロールバーを無効にする設定)

ItemTemplateプロパティへのデータ・テンプレートの設定

 ListBoxコントロールのItemTemplateプロパティに設定するデータ・テンプレートは、[プロパティ]ウィンドウやWPF/Silverlightデザイナのデザイン・ビューを使って作成することはできない。そのため、XAMLビューを使って直接、XAMLコードを記述する。なお、Expression Blendや次期Visual Studioのプレビュー版として公開されているVisual Studio 11 Developer Previewではデザイン・ビューを使用したデータ・テンプレートの作成に対応している。

データ・テンプレート内でスタイルを使用するため、XAMLビューで次のスタイルをベース・レイアウトのGridコントロール(=最上位のタグ(Window/UserControlコントロール)の子要素として配置されている<Grid>タグ)に追加する。

<Grid.Resources>
  <Style TargetType="TextBlock" x:Key="label1">
    <Setter Property="Margin" Value="4,4,2,-2"/>
    <Setter Property="Foreground" Value="#FF5A6779" />
    <Setter Property="Width" Value="60" />
    <Setter Property="TextAlignment" Value="Right" />
  </Style>
  <Style TargetType="TextBlock" x:Key="label2">
    <Setter Property="Margin" Value="4,4,2,-2"/>
    <Setter Property="Foreground" Value="#FF1E395B"/>
  </Style>
  <Style TargetType="ListBoxItem">
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
  </Style>
</Grid.Resources>
一番外側の<Grid>タグの中に記述するスタイルのXAMLコード

XAMLビューで、<ListBox>タグにItemTemplateプロパティへのデータ・テンプレートの設定を追加する。

<ListBox.ItemTemplate>
  <DataTemplate>
    <Border BorderThickness="0,0,0,1" BorderBrush="#FFDCDCDC" Margin="17,0,10,0">
      <Grid Height="53" HorizontalAlignment="Stretch">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto" />
          <ColumnDefinition Width="180"/>
          <ColumnDefinition />
          <ColumnDefinition Width="180" />
        </Grid.ColumnDefinitions>
        <Border Background="White" Margin="0,7,0,18"
             VerticalAlignment="Center" HorizontalAlignment="Center">
          <Border.Effect>
            <DropShadowEffect Color="Gray" Direction="-45" Opacity="0.5" ShadowDepth="2" />
          </Border.Effect>
          <Image Source="{Binding Name}" Width="29" />
        </Border>
        <TextBlock Grid.Column="1" Text="{Binding Name}" FontSize="14.6666666666667" Margin="11,4" />
        <StackPanel Grid.Column="2" Margin="0,5" HorizontalAlignment="Left" >
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="種類:" Style="{StaticResource label1}" />
            <TextBlock Text="{Binding Type}" Style="{StaticResource label2}" />
          </StackPanel>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="大きさ:" Style="{StaticResource label1}" />
            <TextBlock Text="{Binding ImageSize}" Style="{StaticResource label2}" />
          </StackPanel>
        </StackPanel>
        <StackPanel Grid.Column="3" Margin="0,5">
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="撮影日時:" Style="{StaticResource label1}" />
            <TextBlock Text="{Binding CreateDate}" Style="{StaticResource label2}" />
          </StackPanel>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="サイズ:" Style="{StaticResource label1}" />
            <TextBlock Text="{Binding Size}" Style="{StaticResource label2}" />
          </StackPanel>
         </StackPanel>
      </Grid>
    </Border>
  </DataTemplate>
</ListBox.ItemTemplate>
<ListBox>タグの中に記述するデータ・テンプレートの設定のXAMLコード

Imageコントロールの配置と設定

 透過部分を含む画像の場合でも期待するドロップ・シャドウ効果が得られるよう、Borderコントロールの中にImageコントロールを配置する形を取る。ドロップ・シャドウを設定するためのEffectプロパティは、[プロパティ]ウィンドウを使って作成することはできない。そのため、XAMLビューを使って直接、XAMLコードを記述する。なお、Expression Blendや次期Visual Studioのプレビュー版として公開されているVisual Studio 11 Developer Previewでは[プロパティ]ウィンドウからEffectを設定することが可能となっている。

ツールボックスからBorderコントロールをGridコントロールの3列目にドラッグ&ドロップする。

Borderコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

ツールボックスからImageコントロールをBorderコントロールの内側にドラッグ&ドロップする。

Imageコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

[プロパティ]ウィンドウで、Imageコントロールに対して次のプロパティを設定する。

プロパティ
Stretch Uniform

[プロパティ]ウィンドウで、Sourceプロパティの左の列の端にある[プロパティ マーカー]をクリックし、メニューを表示する。そのメニューの[データ バインドの適用]をクリックして[データ バインディング ビルダー]を表示し、次のように設定する。

項目
ソース DataContext - MainViewModel
パス SelectedFile.Name

[ドキュメント アウトライン]ウィンドウを使って、先ほど配置したBorderコントロールを選択する。

[ドキュメント アウトライン]ウィンドウ

[プロパティ]ウィンドウで、Borderコントロールに対して次のプロパティを設定する。

プロパティ
Margin 16
Background White
VerticalAlignment Center
HorizontalAlignment Center

[プロパティ]ウィンドウで、BorderBrushプロパティの左の列の端にある[プロパティ マーカー]をクリックし、表示されるメニューから[値のリセット]を選択する。

[プロパティ]ウィンドウで、BorderThicknessプロパティの左の列の端にある[プロパティ マーカー]をクリックし、表示されるメニューから[値のリセット]を選択する。

XAMLビューで、<Border>タグにEffectプロパティへのドロップ・シャドウ効果を追加する。

<Border.Effect>
  <DropShadowEffect Color="#FFAFAFAF" Direction="-45" Opacity="0.5" ShadowDepth="4" />
</Border.Effect>
<Border>タグの中に記述するドロップ・シャドウ効果の設定のXAMLコード

GridSplitterコントロールの配置と設定

ツールボックスからGridSplitterコントロールをコンテンツ部分のGridコントロールの1列目にドラッグ&ドロップする。

GridSplitterコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

[プロパティ]ウィンドウで、GridSplitterコントロールに対して次のプロパティを設定する。

プロパティ
HorizontalAlignmen Right
Width 1
Background #FFD6E5F5
IsTabStop False

ツールボックスからGridSplitterコントロールをGridコントロールの2列目にドラッグ&ドロップする。

GridSplitterコントロールを右クリックし、コンテキスト・メニューから[レイアウトのリセット]−[すべて]を選択する。

[プロパティ]ウィンドウで、GridSplitterコントロールに対して次のプロパティを設定する。

プロパティ
HorizontalAlignment Right
Width 1
Background #FFD6E5F5
IsTabStop False

 最後に次のページでは、フッタ部分を作成する。


 INDEX
  すぐに使えるWPF/SilverlightのUI開発パターン
  Windowsエクスプローラ型アプリケーション
    1.ヘッダ部分の作成
  2.コンテンツ部分の作成
    3.フッタ部分の作成

インデックス・ページヘ  「すぐに使えるWPF/SilverlightのUI開発パターン」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH