panoramaコントロール指定したitemにスムーズにジャンプ
5639 ワード
panoramaコントロールはwpの中で最も特色のあるコントロールの一つで、wp独自のパノラマビューを提供していますが、このコントロールを使用するとき、私はこのような問題に遭遇しました.コードでpanoramaのSelectedIndexを指定したいのですが、この属性は読み取り専用で、ネットで探すことで、最終的には完璧なソリューションが見つかりません.ネット上のソリューションの多くは以下の通りです.
1.panorama.DefaultItem=panorama.Items[newIndex]を使用する.
この方法はindexのitemを最初の位置に置くだけで、移行したアニメーションはなく、要求に合わない.
2.SelectedItemPropertyという依存属性を設定することでSelectedItemの値を変更します.
しかし、このように設定しても、スライドのアニメーション効果はありません.具体的には、ネットユーザーが提供したコード#コード#を参照してください.
完璧な解決策を得るために、スレ主はpanoramaコントロールのアニメーションの動作方法とそのコントロールテンプレートを深く掘り起こした.最終的にこの問題を解決しました.コードが多いです.次は主な関数です.
アニメーション形式でアイテムに移行する場合は、次のように直接使用します.
最終的な目的を達成するためには、LinqToTreeという利器も必要です.
すべてのコードはここでダウンロードできます:http://vdisk.weibo.com/s/yVSnUWjPhIz8j
注意:wp 8のPanningLayerのGoTo関数には2つのパラメータしかありません.次の行のコードを変更するだけで使用できます.
変更後:
1.panorama.DefaultItem=panorama.Items[newIndex]を使用する.
この方法はindexのitemを最初の位置に置くだけで、移行したアニメーションはなく、要求に合わない.
2.SelectedItemPropertyという依存属性を設定することでSelectedItemの値を変更します.
panorama.SetValue(Panorama.SelectedItemProperty, pan.Items[newIndex]);
しかし、このように設定しても、スライドのアニメーション効果はありません.具体的には、ネットユーザーが提供したコード#コード#を参照してください.
完璧な解決策を得るために、スレ主はpanoramaコントロールのアニメーションの動作方法とそのコントロールテンプレートを深く掘り起こした.最終的にこの問題を解決しました.コードが多いです.次は主な関数です.
/// <summary>
/// Item
/// </summary>
/// <param name="panorama"></param>
/// <param name="index"> Item </param>
/// <param name="duration"> </param>
/// <param name="complated"> </param>
public static void GoTo(this Panorama panorama, int index, Duration duration, Action complated = null)
{
if (panorama.Items.Count == 0)
return;
while (index < 0)
index += panorama.Items.Count;
while (index >= panorama.Items.Count)
index -= panorama.Items.Count;
if (index == panorama.SelectedIndex)
return;
var bgLayer = panorama.Descendants<PanningBackgroundLayer>().FirstOrDefault();
var titleLayer = panorama.Descendants<PanningTitleLayer>().FirstOrDefault();
var itemsLayer = panorama.Descendants<PanningLayer>().LastOrDefault();
var panel = panorama.Descendants<PanoramaPanel>().FirstOrDefault();
if (panel == null)
return;
var direction = -1;
if (index > panorama.SelectedIndex)
{
var length1 = index - panorama.SelectedIndex;
var length2 = panorama.Items.Count - length1;
if (length2 < length1)
direction = 1;
}
else
{
var length1 = panorama.SelectedIndex - index;
var length2 = panorama.Items.Count - length1;
if (length1 <= length2)
direction = 1;
}
var currentOffset = -GetOffsetX(panel, panorama.SelectedIndex);
var offset = -(int) GetOffsetX(panel, index);
if (Math.Sign(offset - currentOffset) != Math.Sign(direction))
{
if (bgLayer != null)
bgLayer.Wraparound(direction);
if (titleLayer != null)
titleLayer.Wraparound(direction);
if (itemsLayer != null)
itemsLayer.Wraparound(direction);
}
panorama.SetValue(Panorama.SelectedItemProperty, panorama.Items[index]);
UpdateItemPositions(panorama, panel);
if (bgLayer != null)
bgLayer.GoTo(offset, duration, null);
if (titleLayer != null)
titleLayer.GoTo(offset, duration, null);
if (itemsLayer != null)
itemsLayer.GoTo(offset, duration, complated);
}
アニメーション形式でアイテムに移行する場合は、次のように直接使用します.
panorama.GoTo(0, new Duration(TimeSpan.FromMilliseconds(800)));
最終的な目的を達成するためには、LinqToTreeという利器も必要です.
すべてのコードはここでダウンロードできます:http://vdisk.weibo.com/s/yVSnUWjPhIz8j
注意:wp 8のPanningLayerのGoTo関数には2つのパラメータしかありません.次の行のコードを変更するだけで使用できます.
if (bgLayer != null)
bgLayer.GoTo(offset, duration, null);
if (titleLayer != null)
titleLayer.GoTo(offset, duration, null);
if (itemsLayer != null)
itemsLayer.GoTo(offset, duration, complated);
変更後:
if (bgLayer != null)
bgLayer.GoTo(offset, duration);
if (titleLayer != null)
titleLayer.GoTo(offset, duration);
if (itemsLayer != null)
itemsLayer.GoTo(offset, duration);
if (complated == null)
return;
var timer = new DispatcherTimer {Interval = duration.TimeSpan};
timer.Tick += (sender, e) =>
{
complated();
timer.Stop();
};
timer.Start();