2020年7月5日日曜日

VB WPF お勉強 15 リストボックス等にアイコンも表示

UI 。
直観的に操作する為に、分かり易い表示は重要です。
殊に、最近のアプリはグラフィカルな要素満載ですし。
では、WPF で、リストボックス等にアイコンも表示させましょうか。


画像アイコンが流行りですね。
文字情報、画像アイコン、共に、長所短所があります。
それを相互に補わせる為に、アイコン+文字 の表示が多用されています。

でも、自前のプログラムでそれを実現しようとすると、
アイコン調達から始めなくてはいけなくて、敷居が高いのではないでしょうか?。

殊に、自分の ListBox や ComboBox に表示する項目で、それをしようとすると、
アイコン作成も必要になる事が多いと思います。

ここでは、その アイコン作成 は棚に上げて、
プログラミングの観点から書いて行きます。
はい。  別途、アイコン用の画像ファイル群 (16px x 16px .png) が揃ったものとして、スタートします。


さて、最初は、WPF でどう実現するか? ですが、
基本的な考え方は、
ComboBox Control を用意し、その各項目を Image + TextBlock で構成する事にしましょう。
はい。  xaml の中で、 ComboBox.ItemTemplate の DataTemplate に WrapPanel を組み込み、
<Image Source="... /> と <TextBlock Text="... /> とで実現させます。
Binding でソースと結び付けたいので、コードは後程。


最初に、アイコンを Resources として、Project に取り入れます。
Project に Resources フォルダを新設し、其処に、.png ファイル群をドロップします。
(Project の リソースタブから既存ファイルを取り込んでも OK です。)
各ファイルの Property から、File Type を Resources 、Build Action を Copy にします。


此処からは、幾通りか方法があると思いますが、
一例としてご覧下さい。


バインドする為に、新たな Class を書き起こします。
各項目の画像と文字列にアクセスする為のクラスになります。
画像は Bitmap に変換済みとします。

クラスのコードです。

Public Class ClassWorkItem
    Public Property Description() As String
    Public Property IconDisp() As Imaging.BitmapImage

    '' Notice!
    ''  Did You Make The File "resource" At Build Action?
    ''      If Not, Error!

    Public Overrides Function ToString() As String
        Return Description
    End Function

    Public Sub New()

    End Sub

    Public Sub New(ByVal description As String,
                   ByVal iconDisp As Imaging.BitmapImage)
        Me.Description = description
        Me.IconDisp = iconDisp
    End Sub

    Public Sub New(ByVal description As String,
                   ByVal iconFileName As String)
        Me.Description = description
        Me.IconDisp = GetBitmapFromResource(iconFileName)
    End Sub

    Friend Function GetBitmapFromResource(ByVal fileName As String) As BitmapImage
        Dim resourcePath As String = "pack://application:,,,/Resources/"
        Dim result As New BitmapImage()
        result.BeginInit()
        result.CacheOption = BitmapCacheOption.OnLoad
        result.UriSource = New System.Uri(resourcePath & fileName)           'Resource:AbsoluteURI
        result.EndInit()
        result.Freeze()
        Return result
    End Function
End Class


次に、
文字列と画像とを結び付けるフィールド変数を定義します。
バインドが前提ですから、ObservableCollection としましょう。

Friend workItems As New ObjectModel.ObservableCollection(Of ClassWorkItem)

そして、ビハインドコードの中で、Load Event 辺りに、
workItems に 文字列と画像のペアで、.Add して行きます。

       workItems.Add(New ClassWorkItem("文字列_01",
                                                   "Icon_01.png"))

肝心なバインド部分は、xaml に、以下のコードを。
これで、項目が選択されると、文字列が返ります。
ですから、その処理を条件分岐で書いて行きましょう。
勿論、項目群の文字列はユニークなもので無ければいけません。
分岐が上手く働かなくなりますから。
また、
項目の将来の追加に備えて、アイコンが未作成の場合の専用アイコンの作成もお忘れ無く!。
或いは、
利用頻度の高いもののみ、アイコンを使う と言ったテクニックもありそうですね。

        <ComboBox x:Name="ComboBox1" HorizontalAlignment="Left" Margin="20,10,0,0" VerticalAlignment="Top" Width="280">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <Image Source="{Binding IconDisp}" Margin="1,1,1,1" Height="16" />
                        <TextBlock Text="{Binding Description}" Margin="8,1,1,1" />
                    </WrapPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>



こうして、書いたものが、以前の投稿 に上げた図中(右)のものになります。
再掲して置きましょう。


文字だけの ComboBox に較べ、画像がある為、直観的に操作が可能になる筈なのですが、
決め手 は、 如何に、ピンッ! と来る画像を用意出来るか、 なのかも知れません。



0 件のコメント:

コメントを投稿