"ControlFader"というカスタムコントロールを作成しました。セレクタプリミティブから継承します。コントロールに追加された項目は、重複するコントロールとして単一のグリッドに配置されます。目的は、選択されたアイテムがフェードインし、以前に選択されたアイテムがフェードアウトするアニメーションを持つことです。キューを介したコントロールのアニメーション化とアニメーション化
まず、不透明度がゼロに設定されたカスタムアイテムコンテナ(ControlFaderItemタイプ)を提供します。次のコードは、(FadeTimeが他の場所で定義されている)ストーリーボードを作成するために使用される:
private Storyboard CreateStoryboard(ControlFaderItem sourceItem, ControlFaderItem targetItem)
{
var fadeControlsStoryboard = new Storyboard();
if (sourceItem != null)
{
var sourceAnimation = new DoubleAnimation(1, 0, FadeTime);
sourceAnimation.SetValue(Storyboard.TargetProperty, sourceItem);
sourceAnimation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(UIElement.OpacityProperty));
fadeControlsStoryboard.Children.Add(sourceAnimation);
}
if (targetItem != null)
{
var targetAnimation = new DoubleAnimation(0, 1, FadeTime);
targetAnimation.SetValue(Storyboard.TargetProperty, targetItem);
targetAnimation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(UIElement.OpacityProperty));
fadeControlsStoryboard.Children.Add(targetAnimation);
}
return fadeControlsStoryboard;
}
Iは次色あせすべき項目を示すためにキューを追加しました。アイテムは、このメソッドを使用してキューから削除されています
private void ProcessQueue()
{
if (isFadeAnimating)
return;
// can't process if there are no queued items
if (FadeQueue.Count == 0)
return;
// get the next item to fade to
var nextItem = FadeQueue.Dequeue();
// locate the index of the item
var itemIndex = Items.IndexOf(nextItem);
if (itemIndex != -1)
SelectedIndex = itemIndex;
}
私は私OnSelectionChangedイベント上書き:
- チェックそれは であればフェードが既にアイテムが起こって、キューされている場合は、フェードを開始
- を
それは次のようになります。
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
// code to simulate an OnSelectionChanging is here (removed for brevity)
// it's used to queue a new selection if isFadeAnimating is true, and reverse the selection
// code to obtain source and target container item also removed for brevity
if (isFadeAnimating)
return;
isFadeAnimating = true;
var storyboard = CreateStoryboard(sourceItem, targetItem);
storyboard.Completed += (s, arg) =>
{
if (sourceItem != null)
sourceItem.Opacity = 0d;
isFadeAnimating = false;
base.OnSelectionChanged(e);
ProcessQueue();
};
storyboard.Begin();
}
何らかの理由で、ストーリーボード完了イベントの内部からProcessQueueを呼び出すと、ストーリーボードが破損しているようです。しかし、フェードの正しいシーケンスが実行された場合に限ります。
インデックス0から1にフェードしてからすぐに0に戻すと、フェードが機能しなくなります。最初のフェードが発生している間にフェードが0に戻されるように十分に速くなければなりません(したがってキューに配置する)。
ControlFaderを使用しているウィンドウで、フェードをトリガーするためにControlFaderのSelectedIndexにバインドします。バインディングはインデックス0から1にフェードした後に0に戻ります。
ProcessQueueへの呼び出しを削除すると、アニメーションとバインディングは決して中断しませんが、フェードは同期していませんキューが処理されていないため、現在のSelectedIndexにする必要があります。
私は困惑しています。助言がありますか?
'ListBoxItem'は' Selected'と 'Unselected'ビジュアルステートを持っていますが、なぜそれらを使わないのですか? –
@Xin興味深い提案ですが、状態アニメーションの1つが行われている場合、どのようにして次のアイテムを追加するのを防ぐことができますか? – mbursill
状態アニメーション中に選択を無効にするのはどうですか? –