xamlで宣言したImageをスクリプトから動かす
はじめに
- 最近WPFを触ってるけど全く分からない
- とりあえず機能単位のサンプルソースを自分で作ると理解した気になれた
やりたかったこと
- xamlで宣言したの画像の位置をスクリプトから動的に変えたかった
やったこと
3通りの方法をやった
- データバインディングを用いて
- Canvasを用いて
- DynamicResorceを用いて
結果
- 1は失敗
- 最初の読み込み時は想定の場所に行くけど、以降動かない
- 2は最低限のことはできたけど、Canvasのレイヤーの上でやる影響で色々厄介
- 3がいい感じだった
どんなコードかいたのか
- 画像をスクリプトで宣言した場所に動かすソースコード達
- 1はMainWindow()で行ってるけど,2と3は関数をつくった
データバインディングを用いて
<Grid>
<Label x:Name="target" Content="動くよ" Margin="{Binding position}" VerticalAlignment="Top" RenderTransformOrigin="0.349,-0.072" Height="50" Width="50"/>
</Grid>
public MainWindow(){
InitializeComponent();
// Thicknessは構造体だからこんな感じでいれる
// 引数はフィールドに宣言か,直でいれるとその場所に表示される
Thickness margin = new Thickness(left, top, right, bottom);
this.DataContext = new { position = margin};
}
- そもそもデータバインディングをざっくりいうとxaml内の{Binding 変数名}に,スクリプトのプロパティの値をいれる見たいなものだと思う
- 起動時は想定の場所に行ってくれる
- 起動以降は座標を弄れなかった…
- 失敗
Canvasを用いて
<Grid Height="350" Width="525">
<Canvas Height="350" Width="525">
<Label x:Name="target" Content="動くよ" VerticalAlignment="Top" RenderTransformOrigin="0.349,-0.072" Height="50" Width="50" Canvas.Top="0" Canvas.Left="0"/>
</Grid>
// 引数にtopとleftをとって,その座標に移動する
private void MoveText(double top, double left) {
Canvas.SetTop(target, top);
Canvas.SetLeft(target, left);
}
- Canvas.SetTop(変数名,top)でxamlで宣言されたCanvasタグに囲まれたオブジェクトをtopに移動
- leftも同様
- 引数の場所に移動出来たし,関数だからスクリプト内でループさせて移動させることができた
- ただ,座標の比率が謎でpixelなげると変な挙動する
- 一応動いたけど没
DynamicResorceを用いて
<Grid>
<Label x:Name="target" Content="動くよ" Margin="{DynamicResource position}" VerticalAlignment="Top" RenderTransformOrigin="0.349,-0.072" Height="50" Width="50"/>
</Grid>
private void MoveText(double left,double top,double right,double bottom) {
Thickness margin = new Thickness(left, top, right, bottom);
this.Resources["textMargin"] = margin;
}
- DynamicResourceはリソースの内容が変更されたら対象のプロパティも変更される
- ただ,移動させるのにmarginを使ってるから,比率を変えないようにするのがめんどくさい
- ちなみに,StaticResourceにすると一度しか値が適用されなくて,データバインディングを使った時みたいになった
- これで行くことにした
DynamicResorceのデモつくった
解説
Update()の実装
public MainWindow() {
InitializeComponent();
FixedTimeProcess();
}
/// <summary>
/// 一定時間でDispatcherTimerTickを実行する関数
/// </summary>
private void FixedTimeProcess() {
// 初期化
dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal);
// 左から 日数、時間、分、秒、ミリ秒で設定
// 1ミリ秒ごとに30回実行
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 10);
dispatcherTimer.Tick += new EventHandler(DispatcherTimerTick);
dispatcherTimer.Start();
}
/// <summary>
/// FixedTimeProcessで実行される関数
/// </summary>
private void DispatcherTimerTick(object sender, EventArgs e) {
// 一定時間毎に処理したい内容をここに記述
}
- UnityのUpdate()見たいな関数を作りたかった
猫の画像を動かす
private void DispatcherTimerTick(object sender, EventArgs e) {
catleft = (catleft < windowWidth / 2) ? catleft + 1 : -40;
catright = (catleft < windowWidth / 2) ? catright - 1 : 240;
MovePic(catleft, 84, catright, 84, "catMargin");
}
/// <summary>
/// テキストの大きさを変える関数
/// </summary>
private void MovePic(double left, double top, double right, double bottom, string target) {
Thickness margin = new Thickness(left, top, right, bottom);
this.Resources[target] = margin;
}
- 今回は左から右に動かすだけだから,marginのtopとbottomは定数とした
- marginのleftをインクリメントして,rightをデクリメントさせることで移動する
- この時,画像本体の横幅が一定になるようにする
- 画面の端に行ったらleftとrightを初期値に戻す
- MovePic()は最初の4つの引数でmarginを設定する
- 最後のstring型の引数で移動させたいtargetの名前をいれる
Read other posts