これは、おそらく GUI スレッドから StartReplay を呼び出しているためです。スレッド処理は、関数が終了した後にのみ続行されます。つまり、関数が完了するまで、GUI は変更を処理できません。GUIスレッドでもあるボタンクリックハンドラーに変更を加えると、関数を終了し、その後GUIに変更が反映されます。そのため、最初の方法はクリックごとに機能します。
あなたができることは、ワーカースレッドを開始してそこで変更を加えることです。または、これはアニメーションのような動作のように見えるため、タイマーを使用します。
更新:
例 1:
DispatcherTimer は、呼び出しスレッドでコールバックを実行します。
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace CanvasAnimation
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer uiTimer;
double directionDelta = 1.0;
public MainWindow()
{
InitializeComponent();
uiTimer = new DispatcherTimer(); //This timer is created on GUI thread.
uiTimer.Tick += new EventHandler(uiTimerTick);
uiTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000/25); // 25 ticks per second
uiTimer.Start();
}
private void uiTimerTick(object sender, EventArgs e)
{
double currentLeft = Canvas.GetLeft(Kwadracik);
if (currentLeft < 0)
{
directionDelta = 1.0;
}
else if (currentLeft > 80)
{
directionDelta = -1.0;
}
currentLeft += directionDelta;
Canvas.SetLeft(Kwadracik, currentLeft);
}
}
}
例 2: シンプルなタイマーの使用
using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace CanvasAnimation
{
/// <summary>
/// Interaction logic for WorkerTimer.xaml
/// </summary>
public partial class WorkerTimer : Window
{
Timer timer;
double directionDelta = 1.0;
public WorkerTimer()
{
InitializeComponent();
timer = new Timer(this.timerTick, this, 0, 1000 / 25); // 25 fPS timer
}
protected void timerTick(Object stateInfo)
{
//This is not a GUI thread!!!!
//So we need to Invoke delegate with Dispatcher
this.Dispatcher.Invoke(new MoveCanvasDelegate(this.moveCanvas), null);
}
protected delegate void MoveCanvasDelegate();
protected void moveCanvas()
{
//This function must be called on GUI thread!!!
double currentLeft = Canvas.GetLeft(Kwadracik);
if (currentLeft < 0)
{
directionDelta = 1.0;
}
else if (currentLeft > 80)
{
directionDelta = -1.0;
}
currentLeft += directionDelta;
Canvas.SetLeft(Kwadracik, currentLeft);
}
}
}
同じ手法が BackgroundWorker またはその他の非 GUI スレッドに適用されます。