Pixtack紫陽花2ndの画像の表示は
XAMLの方でWindow.Resourcesに
Imageコントロールを入れたControlTemplateをThumbコントロールに指定しておいて
VBコードで
- Thumb作成
- Window.ResourcesからControlTemplateを取得
- ThumbにControlTemplateを指定
- ControlTemplateの中のImage取得
- 画像ファイルからBitmapImage作成
- ImageのSourceにBitmapImageを指定
- ThumbをCanvasに追加して表示
この流れで表示している
問題は4番のところでたまにImageを取得できないことがあった
今回これを解決できたっぽいので方法
4番の前、つまり中のImageを取得する前にApplyTemplateを実行する
Thumb.ApplyTemplate
これで解決できたっぽい
FrameworkElement.ApplyTemplate メソッド(System.Windows)
https://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.applytemplate(v=vs.110).aspx
アプリケーションでこのメソッドを呼び出すと、要素のビジュアル ツリーが完全であることが保証されます。この保証のステップは、コードでツリーの子要素をチェックする場合に必要になることがあります。テンプレートは要素の有効期間の適切な時点で自動的に要素に適用されるため、アプリケーション内の一般的な要素のロジックで ApplyTemplate を呼び出す必要はありません。なんか適切な時に自動で処理しているから一般的には呼び出す必要ないって言われているw
でも、どうやらこれを実行するとControlTemplateが再構築されるみたいなので取得に失敗することが無くなった
XAMLとデザイン画面
VBコード
今回で必要なところは48から97行目まで
それ以外はこういうのができたらいいなあのデモ用
'FrameworkElement.ApplyTemplate メソッド(System.Windows)
'https://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.applytemplate(v=vs.110).aspx
'/Knowledge/Programming/WPF/コントロールテンプレート上のボタンのスタイルの動的変更
'http://www.geocities.jp/kandou_quester/Knowledge/Programming/WPF/_change_style_of_button_on_control_template_dinamically.html
'↑参照したところ
Imports System.Windows.Controls.Canvas
Imports System.Windows.Controls.Primitives
Class MainWindow
'Thumbのドラッグ移動用
Private Sub tmb_DragDelta(sender As Object, e As DragDeltaEventArgs)
Dim t As Thumb = DirectCast(sender, Thumb)
Dim x As Double = e.HorizontalChange
Dim y As Double = e.VerticalChange
Dim tx As Double = GetLeft(t)
Dim ty As Double = GetTop(t)
x += tx
y += ty
SetTop(t, y)
SetLeft(t, x)
End Sub
'Thumbの中に画像追加
Private Sub AddImage(cc As Canvas, path As List(Of String), p As List(Of Point))
For i As Integer = 0 To p.Count - 1
Dim b As New BitmapImage(New Uri(path(i)))
Dim img As New Image With {
.Source = b,
.Stretch = Stretch.None,
.Width = b.PixelWidth,
.Height = b.PixelHeight}
SetLeft(img, p(i).X) : SetTop(img, p(i).Y) '描画位置指定
cc.Children.Add(img) '追加
Next
End Sub
''' <summary>
''' Templateを指定したThumbを作成してcanvas1に追加、Templateの中のcCanvasを返す
''' </summary>
''' <param name="p">Thumbの描画位置指定</param>
''' <returns>ThumbのTemplateの中のcCanvas</returns>
Private Function AddThumb(p As Point) As Canvas
Dim t As New Thumb 'Thumb新規作成
'ThumbにTemplate設定
Dim tmp As ControlTemplate = Me.Resources.Item("ct")
t.Template = tmp 'Resources.Item("ct")
'ThumbをCanvasに追加、描画位置指定
SetLeft(t, p.X) : SetTop(t, p.Y)
canvas1.Children.Add(t)
'マウスドラッグ移動イベント用
AddHandler t.DragDelta, AddressOf tmb_DragDelta
'TemplateのVisualTreeを再構築してからでないと中のCanvasを取得できないので
t.ApplyTemplate() '再構築!!!
'そして中のCanvasを取得!!!
Dim cc As Canvas = t.Template.FindName("cCanvas", t)
'cc.Background = New SolidColorBrush(Colors.White) '背景白色
Return cc
End Function
'Button1クリック
'Templateの中のコントロールの取得テスト
Private Sub bt1_Click(sender As Object, e As RoutedEventArgs) Handles bt1.Click
Dim t As New Thumb 'Thumb新規作成
t.Name = "ControlTemplateを適用したThumbです" '目印
'リソースの中からControlTemplateを取得
Dim tmp As ControlTemplate = Me.Resources.Item("ct")
'ThumbにTemplate設定
t.Template = tmp 'Resources.Item("ct")
'ここからTemplateの中のコントロールの取得
Dim emp As Canvas = t.Template.FindName("cCanvas", t)
'↑ここでは取得できない
'先にTemplateのVisualTreeを再構築する必要があるので
t.ApplyTemplate() '再構築!!!
'そして中のコントロールを取得!!!
Dim cc As Canvas = t.Template.FindName("cCanvas", t)
Dim cb As Button = t.Template.FindName("cButton", t)
Dim cl As ListBox = t.Template.FindName("cListbox", t)
Dim cctp As Thumb = DirectCast(cc.TemplatedParent, Thumb)
Dim cbtp As Thumb = DirectCast(cb.TemplatedParent, Thumb)
Dim cltp As Thumb = DirectCast(cl.TemplatedParent, Thumb)
Dim cctpn As String = cctp.Name
End Sub
'Button2クリック
'canvas1に画像追加したThumbを追加
Private Sub bt2_Click(sender As Object, e As RoutedEventArgs) Handles bt2.Click
Dim t As New Thumb
SetLeft(t, 0) : SetTop(t, 0)
canvas1.Children.Add(t)
t.Template = Resources.Item("ct")
t.ApplyTemplate() '再構築!!!
AddHandler t.DragDelta, AddressOf tmb_DragDelta
Dim cc As Canvas = t.Template.FindName("cCanvas", t)
Dim path As New List(Of String)({"D:\ブログ用\テスト用画像\collection_1.png",
"D:\ブログ用\テスト用画像\collection_2.png",
"D:\ブログ用\テスト用画像\collection_3.png"})
Dim p As New List(Of Point)({New Point(10, 10),
New Point(50, 60),
New Point(80, 20)})
Call AddImage(cc, path, p)
End Sub
'Button3クリック
'canvas1に画像追加したThumbを追加
Private Sub bt3_Click(sender As Object, e As RoutedEventArgs) Handles bt3.Click
Dim t As New Thumb
SetLeft(t, 0) : SetTop(t, 0)
canvas1.Children.Add(t)
t.Template = Resources.Item("ct")
t.ApplyTemplate() '再構築!!!
AddHandler t.DragDelta, AddressOf tmb_DragDelta
Dim cc As Canvas = t.Template.FindName("cCanvas", t)
Dim path As New List(Of String)({"D:\ブログ用\テスト用画像\hueRectT210.png",
"D:\ブログ用\テスト用画像\hueRectT255.png",
"D:\ブログ用\テスト用画像\hueRectT300.png"})
Dim p As New List(Of Point)({New Point(10, 10),
New Point(30, 30),
New Point(80, 20)})
Call AddImage(cc, path, p)
End Sub
End Class
それぞれ名前を付けておく、この名前を使って取得することになる
アプリを起動して中のControlを取得して確認してみる
ボタン1が確認ボタン
押すとコードの方に一時停止が指定してあるので
赤の中身が青
85行目でApplyTemplateを実行しているので、その前の82行目では中のControlを取得できていないのでNothingになっている
87行目からの3行ではそれぞれ3つのControlが取得できている(cc, cb, cl)
これで作成したThumbに適用したControlTemplateの中のControlが取得できていることがわかった
ボタン2とボタン3は押すと3つの画像を一つにまとめた画像を表示する
画像をグループ化してまとめて移動できたらいいなあ
こういう画像や表示場所の決め打ちならできたけど、実際にはグループ化解除や画像の選択方法、その編集状態の保存とか入ってくるから難しいし、その前に今のPixtack紫陽花2ndはThumbの中に直接Imageを入れているから複数画像を入れられないから、ImageをCanvasに変更してそこにImageを追加する方法に書き直さないとできない
グループ化も無印の時にはできなかったからなんとかしたいんだよねえ
今回のコード
Wpf_test109_ControlTmplateの中のControl取得 - Visual Studio Team Services
https://gogowaten.visualstudio.com/DefaultCollection/WPF/_git/WPF_test6?path=%2FWpf_test109_ControlTmplate%E3%81%AE%E4%B8%AD%E3%81%AEControl%E5%8F%96%E5%BE%97&version=GBmaster&_a=contents