
WPFで画像のソース(URI)を動的に指定したいです。
例えば以下のようなImageコントロールがあります。
<Image source="hoge.jpg"/>
この「hoge.jpg」ですが、実行環境により配置されるフォルダ(以下リソースフォルダと称します)が変わります。
リソースフォルダのパスはプログラム内で変数で保持しています。
対象の画像が多いので、コードビハインドで毎回「リソースフォルダ+画像名」のパスを指定するのもスマートじゃないなと思ったので
何か良い方法が無いか探しております(なるべくコードビハインドは変更せず、WPFデザイナには画像が反映される方法が良いです)。
開発環境 .net Framework 4.8
例1
WPF側でコンバータを使う方法
・メリット
コードビハインドは汚れない(コンバータの使いまわしができる)
パフォーマンスはまあ大丈夫そう
・デメリット
全体的に冗長。中でもWPFのImage.Sourceの指定があまりにも冗長。
WPFのデザイナに画像が反映されない。
VB.net
1Imports System.Globalization 2 3Class MainWindow 4 Private _ResourcePath As String 5 6 Sub New() 7 InitializeComponent() 8 _ResourcePath = "C:\test\" 'リソースフォルダのパスを指定(最初に一度だけ指定してPG稼働中は変更されない) 9 End Sub 10 11 Public ReadOnly Property ResourcePath As String 12 Get 13 Return _ResourcePath 14 End Get 15 End Property 16End Class 17 18’画像ファイル名をパラメータとして渡す 19Public Class ResourceFolderConverter : Implements IValueConverter 20 Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert 21 Return New Uri(CStr(value) + CStr(parameter)) 22 End Function 23 Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack 24 Throw New NotImplementedException() 25 End Function 26End Class
WPF
1<Window x:Class="MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Window.Resources> 10 <local:ResourceFolderConverter x:Key="ResourceFolderConverter"/> 11 </Window.Resources> 12 <Grid> 13 <Image Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ResourcePath,Converter={StaticResource ResourceFolderConverter},ConverterParameter=hoge.jpg}"/> 14 </Grid> 15</Window>
例2
コードビハインドでImageコントロールを検索して書き換え
・メリット
こちらも使いまわしが可能。コードビハインドも汚れない。
WPFのデザイナに画像が表示される。
WPF側はリソースフォルダを意識する必要がない。
・デメリット
Loadedイベント(レンダリング完了後)に画像の差し替えをしているのでパフォーマンスが不安。
※表示まで1秒以上掛かってしまうと問題ありです(実行環境のスペックもそんなに良くない)。そこそこ容量の大きな画像も使う想定です。
相対パスで参照できる画像も用意しなければならない(画像のビルドアクションをResourceでなく、コンテンツなどにして、exe単体で実行できるようにしたい。)
VB.net
1Imports System.IO 2Imports System.Text.RegularExpressions 3 4Class MainWindow 5 Private _ResourcePath As String 6 7 Sub New() 8 InitializeComponent() 9 _ResourcePath = "C:/test/" 10 End Sub 11 12 Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded 13 For Each img In GetChildrenFromLogical(Of Image)(Me) 14 If TypeOf img.Source Is BitmapFrame Then 15 'ImageのURIを取得 16 Dim imageUri = CType(img.Source, BitmapFrame).Decoder.ToString() 17 'URIのファイル名を取得 18 Dim fileName = System.IO.Path.GetFileName(imageUri) 19 'リソースフォルダとファイル名を結合してセットする。 20 img.Source = New BitmapImage(New Uri(_ResourcePath + fileName)) 21 End If 22 Next 23 End Sub 24 25 '論理ツリーからコントロール要素を取得 26 Private Iterator Function GetChildrenFromLogical(Of T As {DependencyObject})(parent As DependencyObject) As IEnumerable(Of T) 27 For Each child In LogicalTreeHelper.GetChildren(parent) 28 If child IsNot Nothing Then 29 If TypeOf child Is T Then 30 Yield CType(child, T) 31 End If 32 If TypeOf child Is DependencyObject Then 33 For Each descendant In GetChildrenFromLogical(Of T)(CType(child, DependencyObject)) 34 Yield descendant 35 Next 36 End If 37 End If 38 Next 39 End Function 40 41End Class
WPF
1<Window x:Class="MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfApp2" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Grid> 10 <Image Source="hoge.jpg"/> 11 </Grid> 12</Window>
そもそも画像のビルドアクションを全てResourceにすれば済む話なのですが、
「エンドユーザーが任意で画像の差し替えを可能にする」必要があり画像はexeに埋め込めないです。
そこそこ需要がありそうなのに、ここまでしなければならないのか....。という感じです....。
簡単な方法があったら教えてほしい次第です。
よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー