質問編集履歴

3

コメント修正

2022/03/08 08:13

投稿

Mashimasa
Mashimasa

スコア50

test CHANGED
File without changes
test CHANGED
@@ -142,7 +142,7 @@
142
142
  ```
143
143
 
144
144
  そもそも画像のビルドアクションを全てResourceにすれば済む話なのですが、
145
- 「任意で画像の差し替えを可能にする」必要があり画像はexeに埋め込めないです。
145
+ エンドユーザーが任意で画像の差し替えを可能にする」必要があり画像はexeに埋め込めないです。
146
146
 
147
147
  そこそこ需要がありそうなのに、ここまでしなければならないのか....。という感じです....。
148
148
  簡単な方法があったら教えてほしい次第です。

2

コメント追加

2022/03/08 08:12

投稿

Mashimasa
Mashimasa

スコア50

test CHANGED
File without changes
test CHANGED
@@ -97,8 +97,11 @@
97
97
  Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
98
98
  For Each img In GetChildrenFromLogical(Of Image)(Me)
99
99
  If TypeOf img.Source Is BitmapFrame Then
100
+            'ImageのURIを取得
100
101
  Dim imageUri = CType(img.Source, BitmapFrame).Decoder.ToString()
102
+            'URIのファイル名を取得
101
103
  Dim fileName = System.IO.Path.GetFileName(imageUri)
104
+            'リソースフォルダとファイル名を結合してセットする。
102
105
  img.Source = New BitmapImage(New Uri(_ResourcePath + fileName))
103
106
  End If
104
107
  Next
@@ -138,6 +141,9 @@
138
141
  </Window>
139
142
  ```
140
143
 
144
+ そもそも画像のビルドアクションを全てResourceにすれば済む話なのですが、
145
+ 「任意で画像の差し替えを可能にする」必要があり画像はexeに埋め込めないです。
146
+
141
147
  そこそこ需要がありそうなのに、ここまでしなければならないのか....。という感じです....。
142
148
  簡単な方法があったら教えてほしい次第です。
143
149
 

1

サンプルコードなど追加しました。

2022/03/08 08:08

投稿

Mashimasa
Mashimasa

スコア50

test CHANGED
File without changes
test CHANGED
@@ -9,3 +9,137 @@
9
9
  対象の画像が多いので、コードビハインドで毎回「リソースフォルダ+画像名」のパスを指定するのもスマートじゃないなと思ったので
10
10
  何か良い方法が無いか探しております(なるべくコードビハインドは変更せず、WPFデザイナには画像が反映される方法が良いです)。
11
11
 
12
+ 開発環境 .net Framework 4.8
13
+
14
+ 例1
15
+ WPF側でコンバータを使う方法
16
+
17
+ ・メリット
18
+   コードビハインドは汚れない(コンバータの使いまわしができる)
19
+   パフォーマンスはまあ大丈夫そう
20
+
21
+ ・デメリット
22
+    全体的に冗長。中でもWPFのImage.Sourceの指定があまりにも冗長。
23
+    WPFのデザイナに画像が反映されない。
24
+
25
+ ```VB.net
26
+ Imports System.Globalization
27
+
28
+ Class MainWindow
29
+ Private _ResourcePath As String
30
+
31
+ Sub New()
32
+ InitializeComponent()
33
+ _ResourcePath = "C:\test\" 'リソースフォルダのパスを指定(最初に一度だけ指定してPG稼働中は変更されない)
34
+ End Sub
35
+
36
+ Public ReadOnly Property ResourcePath As String
37
+ Get
38
+ Return _ResourcePath
39
+ End Get
40
+ End Property
41
+ End Class
42
+
43
+ ’画像ファイル名をパラメータとして渡す
44
+ Public Class ResourceFolderConverter : Implements IValueConverter
45
+ Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
46
+ Return New Uri(CStr(value) + CStr(parameter))
47
+ End Function
48
+ Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
49
+ Throw New NotImplementedException()
50
+ End Function
51
+ End Class
52
+ ```
53
+
54
+ ```WPF
55
+ <Window x:Class="MainWindow"
56
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
57
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
58
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
59
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
60
+ xmlns:local="clr-namespace:WpfApp1"
61
+ mc:Ignorable="d"
62
+ Title="MainWindow" Height="450" Width="800">
63
+ <Window.Resources>
64
+ <local:ResourceFolderConverter x:Key="ResourceFolderConverter"/>
65
+ </Window.Resources>
66
+ <Grid>
67
+ <Image Source="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=ResourcePath,Converter={StaticResource ResourceFolderConverter},ConverterParameter=hoge.jpg}"/>
68
+ </Grid>
69
+ </Window>
70
+ ```
71
+
72
+ 例2
73
+ コードビハインドでImageコントロールを検索して書き換え
74
+
75
+ ・メリット
76
+   こちらも使いまわしが可能。コードビハインドも汚れない。
77
+   WPFのデザイナに画像が表示される。
78
+   WPF側はリソースフォルダを意識する必要がない。
79
+
80
+ ・デメリット
81
+    Loadedイベント(レンダリング完了後)に画像の差し替えをしているのでパフォーマンスが不安。
82
+     ※表示まで1秒以上掛かってしまうと問題ありです(実行環境のスペックもそんなに良くない)。そこそこ容量の大きな画像も使う想定です。
83
+    相対パスで参照できる画像も用意しなければならない(画像のビルドアクションをResourceでなく、コンテンツなどにして、exe単体で実行できるようにしたい。)
84
+
85
+ ```VB.net
86
+ Imports System.IO
87
+ Imports System.Text.RegularExpressions
88
+
89
+ Class MainWindow
90
+ Private _ResourcePath As String
91
+
92
+ Sub New()
93
+ InitializeComponent()
94
+ _ResourcePath = "C:/test/"
95
+ End Sub
96
+
97
+ Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
98
+ For Each img In GetChildrenFromLogical(Of Image)(Me)
99
+ If TypeOf img.Source Is BitmapFrame Then
100
+ Dim imageUri = CType(img.Source, BitmapFrame).Decoder.ToString()
101
+ Dim fileName = System.IO.Path.GetFileName(imageUri)
102
+ img.Source = New BitmapImage(New Uri(_ResourcePath + fileName))
103
+ End If
104
+ Next
105
+ End Sub
106
+
107
+ '論理ツリーからコントロール要素を取得
108
+ Private Iterator Function GetChildrenFromLogical(Of T As {DependencyObject})(parent As DependencyObject) As IEnumerable(Of T)
109
+ For Each child In LogicalTreeHelper.GetChildren(parent)
110
+ If child IsNot Nothing Then
111
+ If TypeOf child Is T Then
112
+ Yield CType(child, T)
113
+ End If
114
+ If TypeOf child Is DependencyObject Then
115
+ For Each descendant In GetChildrenFromLogical(Of T)(CType(child, DependencyObject))
116
+ Yield descendant
117
+ Next
118
+ End If
119
+ End If
120
+ Next
121
+ End Function
122
+
123
+ End Class
124
+ ```
125
+
126
+ ```WPF
127
+ <Window x:Class="MainWindow"
128
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
129
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
130
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
131
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
132
+ xmlns:local="clr-namespace:WpfApp2"
133
+ mc:Ignorable="d"
134
+ Title="MainWindow" Height="450" Width="800">
135
+ <Grid>
136
+ <Image Source="hoge.jpg"/>
137
+ </Grid>
138
+ </Window>
139
+ ```
140
+
141
+ そこそこ需要がありそうなのに、ここまでしなければならないのか....。という感じです....。
142
+ 簡単な方法があったら教えてほしい次第です。
143
+
144
+ よろしくお願いいたします。
145
+