質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

解決済

WPFで画像を動的に指定したい

Mashimasa
Mashimasa

総合スコア30

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1回答

-1評価

1クリップ

1093閲覧

投稿2022/03/08 05:48

編集2022/03/09 11:25

WPFで画像のソース(URI)を動的に指定したいです。

例えば以下のようなImageコントロールがあります。
<Image source="hoge.jpg"/>
この「hoge.jpg」ですが、実行環境により配置されるフォルダ(以下リソースフォルダと称します)が変わります。

リソースフォルダのパスはプログラム内で変数で保持しています。

対象の画像が多いので、コードビハインドで毎回「リソースフォルダ+画像名」のパスを指定するのもスマートじゃないなと思ったので
何か良い方法が無いか探しております(なるべくコードビハインドは変更せず、WPFデザイナには画像が反映される方法が良いです)。

開発環境 .net Framework 4.8

例1
WPF側でコンバータを使う方法

・メリット
コードビハインドは汚れない(コンバータの使いまわしができる)
パフォーマンスはまあ大丈夫そう

・デメリット
全体的に冗長。中でもWPFのImage.Sourceの指定があまりにも冗長。
WPFのデザイナに画像が反映されない。

VB.net

Imports System.Globalization Class MainWindow Private _ResourcePath As String Sub New() InitializeComponent() _ResourcePath = "C:\test\" 'リソースフォルダのパスを指定(最初に一度だけ指定してPG稼働中は変更されない) End Sub Public ReadOnly Property ResourcePath As String Get Return _ResourcePath End Get End Property End Class ’画像ファイル名をパラメータとして渡す Public Class ResourceFolderConverter : Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert Return New Uri(CStr(value) + CStr(parameter)) End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack Throw New NotImplementedException() End Function End Class

WPF

<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Window.Resources> <local:ResourceFolderConverter x:Key="ResourceFolderConverter"/> </Window.Resources> <Grid> <Image Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ResourcePath,Converter={StaticResource ResourceFolderConverter},ConverterParameter=hoge.jpg}"/> </Grid> </Window>

例2
コードビハインドでImageコントロールを検索して書き換え

・メリット
こちらも使いまわしが可能。コードビハインドも汚れない。
WPFのデザイナに画像が表示される。
WPF側はリソースフォルダを意識する必要がない。

・デメリット
Loadedイベント(レンダリング完了後)に画像の差し替えをしているのでパフォーマンスが不安。
※表示まで1秒以上掛かってしまうと問題ありです(実行環境のスペックもそんなに良くない)。そこそこ容量の大きな画像も使う想定です。
相対パスで参照できる画像も用意しなければならない(画像のビルドアクションをResourceでなく、コンテンツなどにして、exe単体で実行できるようにしたい。)

VB.net

Imports System.IO Imports System.Text.RegularExpressions Class MainWindow Private _ResourcePath As String Sub New() InitializeComponent() _ResourcePath = "C:/test/" End Sub Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded For Each img In GetChildrenFromLogical(Of Image)(Me) If TypeOf img.Source Is BitmapFrame Then            'ImageのURIを取得 Dim imageUri = CType(img.Source, BitmapFrame).Decoder.ToString()            'URIのファイル名を取得 Dim fileName = System.IO.Path.GetFileName(imageUri)            'リソースフォルダとファイル名を結合してセットする。 img.Source = New BitmapImage(New Uri(_ResourcePath + fileName)) End If Next End Sub '論理ツリーからコントロール要素を取得 Private Iterator Function GetChildrenFromLogical(Of T As {DependencyObject})(parent As DependencyObject) As IEnumerable(Of T) For Each child In LogicalTreeHelper.GetChildren(parent) If child IsNot Nothing Then If TypeOf child Is T Then Yield CType(child, T) End If If TypeOf child Is DependencyObject Then For Each descendant In GetChildrenFromLogical(Of T)(CType(child, DependencyObject)) Yield descendant Next End If End If Next End Function End Class

WPF

<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp2" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Image Source="hoge.jpg"/> </Grid> </Window>

そもそも画像のビルドアクションを全てResourceにすれば済む話なのですが、
「エンドユーザーが任意で画像の差し替えを可能にする」必要があり画像はexeに埋め込めないです。

そこそこ需要がありそうなのに、ここまでしなければならないのか....。という感じです....。
簡単な方法があったら教えてほしい次第です。

よろしくお願いいたします。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

SurferOnWww

2022/03/08 07:13

読んでください→ https://teratail.com/help/question-tips 自分ではどこまで実装できていて、どこで躓いていて、何が分かれば解決できるかを、自分が書いたコードをアップするなどして説明できませんか? 今の質問ではなる投げで、ここではマイナス評価対象です。 あと、開発環境を書きましょう。
Mashimasa

2022/03/08 08:08

失礼しました。 開発環境とサンプルコードを追加しました。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです