Quantcast
Channel: 午後わてんのブログ
Viewing all articles
Browse latest Browse all 420

WPFとVB.NET、アプリでの編集状態保存、名前を付けて保存、回転角度を指定する2つの方法

$
0
0

前回
WPFとVB.NETでDataContextやBinding、INotifyPropertyChangedの練習 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14088361.html
の続き

前回のアプリに今の状態をファイルに保存する機能とそのファイルを読み込む機能をつけた、名前を付けて保存とファイルを開く、ゲームで言えばセーブとロード


表示した二つの画像の縦横回転角度をスライダーとボタンで変更
イメージ 1
前回と違うのはBorderから実際の画像ファイルをImageに表示したのと
回転角度を変更できるようになったところ

セーブとロード
状態の保存(セーブ)
イメージ 2
Saveボタンクリックで

イメージ 3
保存画面が出るので適当な名前を付けて保存
ここではsave1にした

イメージ 5
保存されたsave1.zipファイルの中身


保存したファイルを開く
アプリを再起動で初期状態に戻す
イメージ 4
Loadボタンクリックで

イメージ 6
ファイルを開く画面が出るのでさっき保存したsave1を開くと

イメージ 7
保存した時の状態になる


デザイン画面とXAML
イメージ 8

VBコード
イメージ 9

またヤフーブログの文字数制限に引っかかったのでコード部分も画像だけ…


セーブファイルはZip形式で保存するので準備として
System.IO.Compressionを参照に追加しておく
方法は
WPFとVB.NETでデータをシリアライズしてZipファイルに保存 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14077359.html



縦横、回転角度を入れておくクラスSaveData
イメージ 10
前回とほとんど同じだけどこのクラスをシリアライズしてファイルに保存するので
クラスの宣言の頭にSerializableを付けて(230行目)これで良しと実行してみたら

イメージ 11
SerializationException はハンドルされませんでした。
'System.ComponentModel.PropertyChangedEventManager' はシリアル化可能として設定されていません。
っていうエラーが出た

エラーの内容を見るとPropertyChangedってあるからそれっぽい
Public Event PropertyChangedにシリアライズしません!属性のNonSerializedをつけたら、うまく行った(234行目)けどよくわからん


MainWindow
イメージ 12
グローバル変数、選択中の画像の識別のためにImageを入れておくImaImageと
BitmapSource、SaveData、Imageを入れておくリストが3つ
リストはObservableCollectionも使っているけど、普通のListでもいいのかも

アプリ起動時に実行するinitial
イメージ 13
BitmapImageを作成してリストに追加
Imageを作成してリストに追加
SaveDataを作成してリストに追加
Imageの作成の時に回転角度を設定する必要があったので74行目で0度を指定していたけど
イメージ 24
.RenderTransform = New RotateTransform(0)じゃなくて
.RenderTransform = New RotateTransformでよかった
角度指定しなくてもRotateTransformを入れるだけでよかったみたい
今気づいた


Imageの縦横回転角度とSaveDataとSliderのバインディング
Binding、DataContextの設定
この処理はアプリの起動時とセーブファイル読み込んだ直後に実行
イメージ 14
ここが今回の一番の改良点
バインディングのモードにTwoWay(双方向)を指定するようにした
これでImageのWidthやHeightを変更した時でもSaveDataのWidthやHeightも変更されるようになった
SaveDataとImageのWidthプロパティをバインディングする時
前回は
Image.SetBinding(WidthProperty, New Binding("Width"))
今回は
Dim binding as New Binding("Width")
binding.Mode = BindingMode.TwoWay
Image.SetBinding(WidthProperty, binding)

さらに回転角度のBindingの指定の方法は
BindingOperations.SetBinding(Image.RenderTransform, RotateTransform.AngleProperty, binding)
これがわからなくてググッて参照したのがこちら
【WPF】xamlと同等の内容をC#のコードで書いた例 | ザワプロ!
http://zawapro.com/?p=938
ありがとうございます

47行目から49行目までの3行は書く場所間違えている、問題なく動くけど本当は
イメージ 15
Nextの外側のここだわ、今気づいた


名前を付けて保存(セーブ)
イメージ 16
画像ファイルをTiffにエンコード、SaveDataはシリアライズ、この2つを1つのZipファイルにするこの部分は
WPFとVBで複数画像(BitmapSource)とシリアライズした文字列(String)や数値(Integerとか)を1つのZipファイルにする ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14079902.html
この時とほぼ同じ、だけどムダなことしていたっぽいところを除いた
Stream関連はわかっていないからまだムダなことしてるかも
Zipの圧縮レベル指定にCompressionLevel.Fastestを指定するようにしたけど
指定しなくても同じみたい

保存したZipファイルを読み込み
イメージ 17
こちらもムダを取り除いたのと
画像読み込んでリストに追加するとことを少し変えただけ
For i As Integer = 0 to TiffBitmapDecoder.Frames.Count -1
bitmapList.Add(TiffBitmapDecoder.Frames(i))
Next
これを
bitmapList.AddRange(TiffBitmapDecoder.Frames)
に変えた

イメージ 18
この辺は各イベントの時にさっきまでのを呼び出しているだけ

画像をクリックした時の処理
イメージ 19
これもBorderがImageに変わっただけで前回と同じ

Button1と2を押した時の処理
イメージ 20
選択中の画像の横幅と回転角度を変えている
Button1での処理は選択中のImageのDataContextからSaveDataを取得して
その中のプロパティに値を指定している
Button2での処理はDataListの中からSaveDataを取得して
その中のプロパティに値を指定している
どちらもできるみたいなのでどちらを使おうかなあってところ
特別なことがなければButton1の方法がラクかな

Button3クリックした時の処理
イメージ 21
横幅と回転角度を選択中のImageに直接指定している
前回はこれが期待通りに動かせなかったけど解消できた
1つはさっき(19行目から)のバインディングのモードを双方に指定することで
もう1つがさっき(26行目)でBindingOperationsを使ってバインディングする方法に関連しているけど、回転角度の指定の方法を変えたこと
回転角度を60度に指定する時
前回は
Image.RenderTransform = New RotateTransform(60)
こうしていたのを今回は
Image.RenderTransform.SetValue(RotateTransform.AngleProperty, 60.0R)
こう変えた

回転角度の指定の方法が良くないんだなあと思っていて、それでもRenderTransformはあっているだろうから、その中でなんか良さそうなのがないかなあって一覧表を眺めていたら
イメージ 22
SetValue、これ良さそう、でも使い方がわからん
ググッて
x:NameもしくはFindNameの怪 その1 - k_maruの思うところ2
http://kmaru.hatenablog.com/entry/20081216/1229437297
silverlight - XAML: make a ScrollViewer show scrollbars When the ScaleTransform Of a child Object gets big - Stack Overflow
http://stackoverflow.com/questions/2394370/xaml-make-a-scrollviewer-show-scrollbars-when-the-scaletransform-of-a-child-obj
助かりました

前回の方法だとバインディングが外れてしまったように無効になっていたのは、RotateTransformを上書きする形になっていたのから?
今回の方法ではRotateTransformはそのままで、そのなかのAnglePropertyの値だけ変更するような形だからバインディングはそのまま保たれているってことかなあ
あとはAnglePropertyに指定する値はDouble型だからなのか普通に60って指定するとエラー
イメージ 23
これはなんか方法があったはずだなあってググッてこちら
リテラルとサフィックス -Programming / .NET Framework/基本的なデータ型 - 総武ソフトウェア推進所
        'http://smdn.jp/programming/netfx/basic_types/1_literal_suffix/
ありがとうございます

60.0RってRを数値の後ろに付け加えればいいみたい
他には#を付けるか、小数点以下まで入れる
でもなんでRなんだろうねえ

そんなこんなでなんとかできた
今回のでテストが終わったので次は本番のPixtack紫陽花2ndに名前を付けて保存を付ける、時間かかりそうだなあ

Imageとかの回転角度を指定するときは最初だけ
Image.RenderTransform = New RotateTransform(30)
こんなふうにNewでRotateTransformを作ったのを指定して
それ以降は例えば60度に変更するときはSetValueを使って
Image.RenderTransform.SetValue(RotateTransform.AngleProperty, 60.0R)
こうするのがいい…のかな

コード


関連記事
WPFとVB.NET、複数のBitmapSourceを1つにしてシリアライズしてファイルに保存 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14072509.html

WPFとVB.NETでデータをシリアライズしてZipファイルに保存 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14077359.html

WPFとVBで複数画像(BitmapSource)とシリアライズした文字列(String)や数値(Integerとか)を1つのZipファイルにする ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14079902.html

WPFとVB.NETでDataContextやBinding、INotifyPropertyChangedの練習 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14088361.html




Viewing all articles
Browse latest Browse all 420

Trending Articles