|
// From:
// WPBehaviorsLibrary
// http://aimeegurl.com/2010/03/18/panoramic-navigation-on-windows-phone-7-with-no-code/
//
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
namespace BehaviorsLibrary
{
/// <summary>
/// Action to implement VisualStateManager.GoToState.
/// Navigates the context which this action resides.
/// </summary>
[DefaultTrigger(typeof(ButtonBase), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "Click" }),
DefaultTrigger(typeof(UIElement), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "MouseLeftButtonDown" })]
public class GoToState : TargetedTriggerAction<FrameworkElement>
{
/// <summary>
///
/// </summary>
public static readonly DependencyProperty StateNameProperty = DependencyProperty.Register("StateName", typeof(string), typeof(GoToState), new PropertyMetadata(null));
/// <summary>
/// The name of the state which is to be activated.
/// </summary>
public string StateName
{
get { return (string)this.GetValue(GoToState.StateNameProperty); }
set { this.SetValue(GoToState.StateNameProperty, value); }
}
/// <summary>
///
/// </summary>
public static readonly DependencyProperty UseTransitionsProperty = DependencyProperty.Register("UseTransitions", typeof(bool), typeof(GoToState), new PropertyMetadata(true));
/// <summary>
/// True if transitions are to be used for the state change.
/// </summary>
public bool UseTransitions
{
get { return (bool)this.GetValue(GoToState.UseTransitionsProperty); }
set { this.SetValue(GoToState.UseTransitionsProperty, value); }
}
/// <summary>
/// Implementation of the Invoke.
/// </summary>
/// <param name="arguments"></param>
protected override void Invoke(object arguments)
{
Control targetControl = this.TargetControl;
if (targetControl != null && !string.IsNullOrEmpty(this.StateName))
{
VisualStateManager.GoToState(targetControl, this.StateName, this.UseTransitions);
}
}
/// <summary>
/// Get the control which this action should be changing the state of.
/// The control is always the parent in the logical tree which contains a VSM. If this
/// action is attached to a button in UserControl.xaml, then the state group should be the
/// UserControl's state group- not the Button's.
/// </summary>
private Control TargetControl
{
get
{
FrameworkElement parent = this.Target as FrameworkElement;
bool foundVSM = false;
while (parent != null)
{
if (!foundVSM)
{
IList vsgs = VisualStateManager.GetVisualStateGroups(parent);
if (vsgs != null && vsgs.Count > 0)
foundVSM = true;
}
if (foundVSM)
{
Control parentControl = parent as Control;
if (parentControl != null)
return parentControl;
}
parent = parent.Parent as FrameworkElement;
}
return null;
}
}
}
/// <summary>
/// Base class for a number of GoToState triggers.
/// </summary>
public abstract class GoToStateBase : TargetedTriggerAction<FrameworkElement>
{
private int currentStateIndex = 0;
/// <summary>
///
/// </summary>
public static readonly DependencyProperty UseTransitionsProperty = DependencyProperty.Register("UseTransitions", typeof(bool), typeof(GoToStateBase), new PropertyMetadata(true));
/// <summary>
/// True if transitions should be used for the state change.
/// </summary>
public bool UseTransitions
{
get { return (bool)this.GetValue(GoToStateBase.UseTransitionsProperty); }
set { this.SetValue(GoToStateBase.UseTransitionsProperty, value); }
}
/// <summary>
/// Hooks up necessary handlers for the state changes.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
Control control = this.TargetControl;
if (control != null)
{
foreach (VisualStateGroup vsg in this.TargetVSM)
{
vsg.CurrentStateChanged += this.HandleStateChanged;
}
}
else
{
Dispatcher.BeginInvoke(delegate
{
this.OnAttached();
});
}
}
/// <summary>
/// Cleans up when getting removed.
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
Control control = this.TargetControl;
if (control != null)
{
foreach (VisualStateGroup vsg in this.TargetVSM)
{
vsg.CurrentStateChanged -= this.HandleStateChanged;
}
}
}
private void HandleStateChanged(object sender, VisualStateChangedEventArgs e)
{
int index = 0;
foreach (VisualStateGroup vsg in this.TargetVSM)
{
foreach (VisualState state in vsg.States)
{
if (state == e.NewState)
{
this.currentStateIndex = index;
}
++index;
}
}
}
/// <summary>
/// The total number of states in the targetted VSM.
/// </summary>
protected int StateCount
{
get
{
int count = 0;
foreach (VisualStateGroup vsg in this.TargetVSM)
foreach (VisualState state in vsg.States)
++count;
return count;
}
}
/// <summary>
/// The index of the current state in the targetted VSM.
/// </summary>
protected int CurrentStateIndex
{
get { return this.currentStateIndex; }
}
/// <summary>
/// Goes to the specified state on the targetted VSM.
/// </summary>
/// <param name="targetIndex">index of the state to be activated</param>
/// <param name="useTransitions">True if transitions should be used.</param>
protected void GoToState(int targetIndex, bool useTransitions)
{
Control targetControl = this.TargetControl;
if (targetControl == null)
return;
int index = 0;
foreach (VisualStateGroup vsg in this.TargetVSM)
{
foreach (VisualState state in vsg.States)
{
if (index == targetIndex)
{
VisualStateManager.GoToState(targetControl, state.Name, useTransitions);
break;
}
++index;
}
}
}
/// <summary>
/// Get the control which this action should be changing the state of.
/// The control is always the parent in the logical tree which contains a VSM. If this
/// action is attached to a button in UserControl.xaml, then the state group should be the
/// UserControl's state group- not the Button's.
/// </summary>
private Control TargetControl
{
get
{
return GoToStateBase.FindTargetControl(this.Target);
}
}
private IList<VisualStateGroup> TargetVSM
{
get
{
return GoToStateBase.FindVSM(this.Target);
}
}
internal static Control FindTargetControl(FrameworkElement element)
{
FrameworkElement parent = element;
bool foundVSM = false;
while (parent != null)
{
if (!foundVSM)
{
IList vsgs = VisualStateManager.GetVisualStateGroups(parent);
if (vsgs != null && vsgs.Count > 0)
foundVSM = true;
}
if (foundVSM)
{
Control parentControl = parent as Control;
if (parentControl != null)
return parentControl;
}
parent = parent.Parent as FrameworkElement;
}
return null;
}
internal static IList<VisualStateGroup> FindVSM(FrameworkElement element)
{
FrameworkElement parent = element;
bool foundVSM = false;
List<VisualStateGroup> stateGroups = new List<VisualStateGroup>();
while (parent != null)
{
if (!foundVSM)
{
IList vsgs = VisualStateManager.GetVisualStateGroups(parent);
if (vsgs != null && vsgs.Count > 0)
{
foreach (VisualStateGroup vsg in vsgs)
stateGroups.Add(vsg);
return stateGroups;
}
}
parent = parent.Parent as FrameworkElement;
}
return stateGroups;
}
/// <summary>
///
/// </summary>
public static readonly DependencyProperty LoopProperty = DependencyProperty.Register("Loop", typeof(bool), typeof(GoToStateBase), new PropertyMetadata(false));
/// <summary>
/// True if this should loop around when it gets to the end.
/// </summary>
public bool Loop
{
get { return (bool)this.GetValue(GoToStateBase.LoopProperty); }
set { this.SetValue(GoToStateBase.LoopProperty, value); }
}
}
/// <summary>
/// Go to the next state in the targetted VSM.
/// </summary>
[DefaultTrigger(typeof(ButtonBase), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "Click" }),
DefaultTrigger(typeof(UIElement), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "MouseLeftButtonDown" })]
public class GoToNextState : GoToStateBase
{
/// <summary>
/// Does the state transition.
/// </summary>
/// <param name="parameter"></param>
protected override void Invoke(object parameter)
{
int index = this.CurrentStateIndex + 1;
if (index >= this.StateCount && this.Loop)
index = 0;
this.GoToState(index, this.UseTransitions);
}
}
/// <summary>
/// Go to the previous state in the targetted VSM.
/// </summary>
[DefaultTrigger(typeof(ButtonBase), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "Click" }),
DefaultTrigger(typeof(UIElement), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "MouseLeftButtonDown" })]
public class GoToPreviousState : GoToStateBase
{
/// <summary>
/// Does the state transition.
/// </summary>
/// <param name="parameter"></param>
protected override void Invoke(object parameter)
{
int index = this.CurrentStateIndex - 1;
if (index < 0 && this.Loop)
index = this.StateCount - 1;
this.GoToState(index, this.UseTransitions);
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I've been playing with computers since my first Acorn Electron, & after blowing up a few ZX Spectrums. I moved on to the C64 & Amiga, & eventually reluctantly on to the PC.
I have learnt a wide set of skills during my 38 years of existence, living in the UK, on the sunny south coast.
My main area of expertise is Graphic/Visual Design, Usability & UI Design. I am not a programmer, but am fairly technically minded due to studying Mechanical Engineering at Uni.
I have work both Freelance & for IBM as a Graphic Designer, & am skilled in the usual graphics packages like, PhotoShop, CorelDraw or Illustrator, Premier, Dreamweaver, Flash etc.
But I originally started with Lightwave & 3D animation.