I got a Stackpanel containing many buttons, so how can I reorder my buttons by draging & droping them like Expression Blend or "Visual Studio Xaml Window Designer" does
This thread provides some useful information. Nevertheless, there are a lot of resources that you can find in by searching which would provide a lot of information on this.
I am developing an arrangeable stack panel, when I touch or press the item and release the mouse and move the object or child in the stack panel is stick with it. my Code is as below.
namespace Controls.ArrangableGrid
{
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Documents;
public class ArrangableControl : StackPanel
{
#region - Variables -
private bool _isDown;
private bool _isDragging;
private Point _startPoint;
private DragAdorner _adorner;
private UIElement _draggedItem = null;
private int _draggedItemIndex = -1;
private ILoggingService _logging = null;
private ILogger _logger;
private CypherComponentModel _parentComponent = null;
#endregion
public ArrangableControl()
{
Orientation = Orientation.Horizontal;
Background = Brushes.Transparent;
if (!DesignerProperties.GetIsInDesignMode(this))
{
Loaded += OnLoaded;
}
}
#region - Functions -
private void SetEvetns()
{
AllowDrop = true;
Drop += OnDrop;
StylusDown += OnEventDown;
StylusUp += OnEventUp;
StylusMove += OnEventMove;
MouseLeftButtonDown += OnEventDown;
MouseLeftButtonUp += OnEventUp;
MouseMove += OnEventMove;
}
private Point GetPosition(InputEventArgs e, IInputElement obj)
{
if (e is MouseEventArgs)
{
Mouse.Capture(obj);
return (e as MouseEventArgs).GetPosition(obj);
}
else if (e is TouchEventArgs)
{
(e as TouchEventArgs).TouchDevice.Capture(obj);
return (e as TouchEventArgs).GetTouchPoint(obj).Position;
}
else if (e is StylusEventArgs)
{
Stylus.Capture(obj);
return (e as StylusEventArgs).GetPosition(obj);
}
return new Point();
}
private void DragStarted()
{
if (_draggedItem == null) return;
_isDragging = true;
_adorner = new DragAdorner(_draggedItem);
var layer = AdornerLayer.GetAdornerLayer(_draggedItem);
layer.Add(_adorner);
}
private void DragMoved()
{
var currentPosition = Mouse.GetPosition(this);
_adorner.LeftOffset = currentPosition.X - _startPoint.X;
_adorner.TopOffset = currentPosition.Y - _startPoint.Y;
}
private void DragFinished(bool cancelled, InputEventArgs e)
{
this.ReleaseMouseCapture();
if (null != _adorner)
AdornerLayer.GetAdornerLayer(_adorner.AdornedElement).Remove(_adorner);
if (cancelled == false)
{
UIElement _dropItem = this.GetChildElement(GetPosition(e, this)) as UIElement;
if (null != _dropItem)
DragDrop.DoDragDrop(_draggedItem, new DataObject("UIElement", e.Source, true), DragDropEffects.Move);
}
_adorner = null;
_isDragging = false;
_isDown = false;
}
#endregion
#region - Events -
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (this.IsLoaded)
{
SetEvetns();
}
}
private void OnEventDown(object sender, InputEventArgs e)
{
if(e.Source != this)
{
_isDown = true;
_isDragging = false;
_startPoint = GetPosition(e, this);
_draggedItem = e.Source as UIElement;
if (null != _draggedItem)
_draggedItemIndex = this.Children.IndexOf(_draggedItem);
}
}
private void OnEventUp(object sender, InputEventArgs e)
{
if (_isDown && _isDragging)
{
DragFinished(false, e);
e.Handled = true;
}
else
{
e.Handled = true;
ReleaseMouseCapture();
ReleaseAllTouchCaptures();
ReleaseStylusCapture();
}
}
private void OnEventMove(object sender, InputEventArgs e)
{
if (_isDown)
{
if ((_isDragging == false) &&
((Math.Abs(GetPosition(e, this).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(GetPosition(e, this).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
DragStarted();
if (_isDragging)
DragMoved();
}
e.Handled = true;
}
private void OnDrop(object sender, DragEventArgs e)
{
try
{
UIElement droptarget = e.Source as UIElement;
int droptargetIndex = this.Children.IndexOf(droptarget);
if (_draggedItem != null && (droptargetIndex != _draggedItemIndex))
{
if (droptargetIndex != -1)
{
this.Children.Remove(_draggedItem);
this.Children.Insert(droptargetIndex, _draggedItem);
}
}
_draggedItem = null;
_draggedItemIndex = -1;
}
catch (Exception ex)
{
_logger.Error($"Drop Error: {ex} at {nameof(ArrangableControl)}");
}
finally
{
e.Handled = true;
ReleaseMouseCapture();
ReleaseAllTouchCaptures();
ReleaseStylusCapture();
}
}
#endregion
}
}
Related
I use dragging control by mouse
Problem is if Control.Enabled = false. Dragging can't work? Is there any method to overload to prevent this behavior?
static void control_MouseEnter(object sender, EventArgs e)
{
(sender as Control).Enabled = false;
(sender as Control).Cursor = Cursors.SizeAll;
}
static void control_MouseLeave(object sender, EventArgs e)
{
(sender as Control).Enabled = true;
// (sender as Control).Cursor = Cursors.Default;
}
static void control_MouseDown(object sender, MouseEventArgs e)
{
mouseLocation = e.Location;
// turning on dragging
draggables[(Control)sender] = true;
}
static void control_MouseUp(object sender, MouseEventArgs e)
{
// turning off dragging
draggables[(Control)sender] = false;
}
static void control_MouseMove(object sender, MouseEventArgs e)
{
// only if dragging is turned on
if (draggables[(Control)sender] == true)
{
var control = (sender as Control);
control.Left = e.X + control.Left - mouseLocation.X;
control.Top = e.Y + control.Top - mouseLocation.Y;
}
}
You could use IMessageFilter to trap WM_MOUSEMOVE.
Here I'm changing the caption of the form when the mouse is moved within pictureBox1. It also tells you whether the left mouse button is down:
public partial class Form1 : Form
{
private MyFilter mf;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Enabled = false;
mf = new MyFilter();
mf.PreFilterMouseMove += Mf_PreFilterMouseMove;
Application.AddMessageFilter(mf);
}
private void Mf_PreFilterMouseMove()
{
Point pt = pictureBox1.PointToClient(Cursor.Position);
if (pictureBox1.ClientRectangle.Contains(pt))
{
bool leftDown = (Control.MouseButtons == MouseButtons.Left);
this.Text = "leftDown = " + leftDown + " : position = " + pt.ToString();
}
else
{
this.Text = "...not within pictureBox1...";
}
}
}
public class MyFilter : IMessageFilter
{
private const int WM_MOUSEMOVE = 0x200;
public delegate void dlgMouseMove();
public event dlgMouseMove PreFilterMouseMove;
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_MOUSEMOVE:
if (PreFilterMouseMove != null)
{
PreFilterMouseMove();
}
break;
}
return false;
}
}
I want to drag the listbox selected item. Dragging function is working fine. My requirement is dragging should not happen while drag started from any other location in listbox. I have did like this, but that is not working. Please anyone suggest me to achieve this,
private bool IsDragging { get; set; }
private Point _startPoint { get; set; }
protected override void OnAttached()
{
this.AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
this.AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;
}
private void AssociatedObject_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && !IsDragging)
{
Point position = e.GetPosition(null);
if (Math.Abs(position.X - _startPoint.X) <= SystemParameters.MinimumHorizontalDragDistance &&
Math.Abs(position.Y - _startPoint.Y) <= SystemParameters.MinimumVerticalDragDistance)
{
StartDrag(sender);
}
}
}
private void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
private void StartDrag(object sender)
{
IsDragging = true;
if (sender is ListBox)
{
var listBox = (sender as ListBox);
if (listBox != null)
{
var selectedMember = listBox.SelectedItem;
if (selectedMember != null)
{
DragDrop.DoDragDrop(listBox, selectedMember, DragDropEffects.Copy);
}
}
}
IsDragging = false;
}
Please refer the screenshot
Do like this, By using System.Windows.Media.VisualTreeHelper.HitTest(this, point) it gives the current element under the mouse. I think it will help you.
private bool IsDrag { get; set; }
protected override void OnAttached()
{
this.AssociatedObject.Drop += AssociatedObject_Drop;
this.AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObject_PreviewMouseLeftButtonDown;
this.AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;
}
private void AssociatedObject_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if(IsDrag)
{
StartDrag(sender);
}
}
}
private void AssociatedObject_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
IsDrag = false;
if(sender is ListBox)
{
Point initialPoint = e.GetPosition((UIElement)sender);
var histPoint = VisualTreeHelper.HitTest(sender as ListBox, initialPoint);
if (histPoint.VisualHit != null)
{
if (histPoint.VisualHit is TextBlock || histPoint.VisualHit is Border)
{
IsDrag = true;
}
}
}
}
private void StartDrag(object sender)
{
if (sender is ListBox)
{
var listBox = (sender as ListBox);
if (listBox != null)
{
var selectedMember = listBox.SelectedItem;
if (selectedMember != null)
{
DragDrop.DoDragDrop(listBox, selectedMember, DragDropEffects.Copy);
}
}
}
}
I keep seeing posts about adding Events to be able to drag around the panel. But how would i achieve this through a dynamically created Panel?
Panel pn = wch.GenerateWorkspaceControl(space.Name, space.Name, p);
PanelTest.Controls.Add(pn);
public Panel GenerateWorkspaceControl(string gbTitle, string gbName, Point gbPos)
{
Panel pnl = GeneratePanelContainer(gbPos, new Size(300, 200));
pnl.Controls.Add(GenerateLabel(gbName,new Point(100,1),new Size(135,115)));
return pnl;
}
private Panel GeneratePanelContainer(Point loc, Size size)
{
return new Panel() { BackColor = Color.Transparent, BorderStyle = BorderStyle.FixedSingle, Location = loc, Size = size };
}
Do i add an event handler in the generate panel container?
to summarize i have a panel that is holding multiple panels that are dynamically created. I want to be able to move around the dynmaically created panels INSIDE the main panel.
Any ideas?
Here is a class that lets you make any control movable.
Simply register it:
MoveController.RegisterCtl( button1 );
Now you can move the control..
When done you can also unregister a control:
MoveController.UnRegisterCtl( button1 );
Here is the controller class:
static class MoveController
{
static List<Control> Controls = new List<Control>();
static Control curCtl = null;
static Point curStart = Point.Empty;
static public void RegisterCtl(Control ctl)
{
Controls.Add(ctl);
ctl.MouseDown += ctl_MouseDown;
ctl.MouseMove += ctl_MouseMove;
ctl.MouseUp += ctl_MouseUp;
}
static public void UnRegisterCtl(Control ctl)
{
if (Controls != null && Controls.Contains(ctl) )
{
Controls.Remove(ctl);
ctl.MouseDown -= ctl_MouseDown;
ctl.MouseMove -= ctl_MouseMove;
ctl.MouseUp -= ctl_MouseUp;
}
}
static void ctl_MouseDown(object sender, MouseEventArgs e)
{
curCtl = (Control)sender;
curStart = curCtl.Location;
}
static void ctl_MouseMove(object sender, MouseEventArgs e)
{
if (curCtl != null)
{
curCtl.Left += e.Location.X - curCtl.Width / 2;
curCtl.Top += e.Location.Y - curCtl.Height / 2;
}
}
static void ctl_MouseUp(object sender, MouseEventArgs e)
{
curCtl = null;
}
}
Update
Here is a more involved version that allows
to set a Tag value to restrict movement to vertical or horizontal
adding Actions for Moving and Moved events..
class MoveController
{
static List<Control> Controls = new List<Control>();
static Control curCtl = null;
static Point curStart = Point.Empty;
static Dictionary<Control, Tuple<Action, Action>>
actions = new Dictionary<Control, Tuple<Action, Action>>();
static public void RegisterCtl(Control ctl)
{
RegisterCtl(ctl, null, null);
}
static public void RegisterCtl(Control ctl, Action moveAction, Action movedAction)
{
Controls.Add(ctl);
ctl.MouseEnter += Ctl_MouseEnter;
ctl.MouseLeave += Ctl_MouseLeave;
ctl.MouseDown += ctl_MouseDown;
ctl.MouseMove += ctl_MouseMove;
ctl.MouseUp += ctl_MouseUp;
if (moveAction != null)
if (actions.Keys.Contains(ctl)) actions[ctl] = new Tuple<Action, Action>(moveAction, movedAction);
else actions.Add(ctl, new Tuple<Action, Action>(moveAction, movedAction));
}
private static void Ctl_MouseEnter(object sender, EventArgs e)
{
((Control)sender).Cursor = Cursors.Hand;
}
private static void Ctl_MouseLeave(object sender, EventArgs e)
{
((Control)sender).Cursor = Cursors.Default;
}
public static void UnRegisterCtl(Control ctl)
{
if (Controls != null && Controls.Contains(ctl) )
{
Controls.Remove(ctl);
ctl.MouseDown -= ctl_MouseDown;
ctl.MouseMove -= ctl_MouseMove;
ctl.MouseUp -= ctl_MouseUp;
}
if (actions.ContainsKey(ctl)) actions.Remove(ctl);
}
static public void RegisterMovingAction(Control ctl, Action action)
{
}
static void ctl_MouseDown(object sender, MouseEventArgs e)
{
curCtl = (Control)sender;
curStart = curCtl.Location;
}
static void ctl_MouseMove(object sender, MouseEventArgs e)
{
int t = 0;
if (curCtl != null)
{
if (curCtl.Tag != null) t = Convert.ToInt32(curCtl.Tag);
if ((t&1) != 1) curCtl.Left += e.Location.X - curCtl.Width / 2;
if ((t&2) != 2) curCtl.Top += e.Location.Y - curCtl.Height / 2;
if (actions.ContainsKey(curCtl) && actions[curCtl] != null && actions[curCtl].Item1 != null)
actions[curCtl].Item1();
}
}
static void ctl_MouseUp(object sender, MouseEventArgs e)
{
if (curCtl == null) return; ///
if (actions.ContainsKey(curCtl) && actions[curCtl] != null && actions[curCtl].Item2 != null)
actions[curCtl].Item2();
curCtl = null;
}
}
When the code in the event TextChanged was inside the event TextBoxURL_KeyDown it was working fine also with the logic i wanted. But then i had to press the enter key, so i moved it to the TextChanged event but now when i type a valid in the TextBoxUrl nothing happens.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DownloadMultipleFiles
{
public partial class AddNewDownloads : Form
{
public AddNewDownloads()
{
InitializeComponent();
foreach (Control ctrl in this.Controls)
{
if ((ctrl as TextBox) != null)
{
(ctrl as TextBox).TextChanged += TextChanged;
}
}
this.TextBoxURL.KeyDown += new KeyEventHandler(TextBoxURL_KeyDown); //add keyDown event
if (TextBoxFilename.Text == "" || TextBoxBrowse.Text == "")
{
TextBoxFilename.Enabled = false;
TextBoxBrowse.Enabled = false;
btnOK.Enabled = false;
}
}
private void AddNewDownloads_Load(object sender, EventArgs e)
{
}
private void btnBrowse_Click(object sender, EventArgs e)
{
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnOK_Click(object sender, EventArgs e)
{
}
private void TextBoxURL_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter) //validate the URL when you press the Enter key
{
}
}
private bool CheckValidUrl() // validate from clipboard
{
string isUrl = Clipboard.GetText();
Uri uriResult;
bool result = Uri.TryCreate(isUrl, UriKind.Absolute, out uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
return result;
}
private bool WriteValidUrl() // validate manual input
{
string pattern2 = #"^http://www.[a-z].com$";
Match match = Regex.Match(TextBoxURL.Text, pattern2);
if (match.Success)
return true;
else
return false;
}
private new void TextChanged(object sender, EventArgs e)
{
if (CheckValidUrl() == true || WriteValidUrl() == true)
{
TextBoxFilename.Enabled = true;
TextBoxBrowse.Enabled = true;
btnOK.Enabled = true;
}
else
{
TextBoxFilename.Enabled = false;
TextBoxBrowse.Enabled = false;
btnOK.Enabled = false;
}
if (TextBoxURL.Text == "")
{
TextBoxFilename.Enabled = false;
TextBoxBrowse.Enabled = false;
btnOK.Enabled = false;
}
}
}
}
TextChanged fires on exit of the textbox. You might be looking for KeyDown or KeyUp, or KeyPress - probably KeyUp as this will allow you to capture what is in the textbox after the new character is added.
I am trying to implement Fast app resume for Windows Phone 8. I followed the link at MSDN.
And here is the code in XAML:
<Tasks>
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume"/>
</Tasks>
And this is the code in app.xaml.cs
public static PhoneApplicationFrame RootFrame { get; private set; }
bool wasRelaunched = false;
bool mustClearPagestack = false;
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
enum SessionType
{
None,
Home,
DeepLink
}
private SessionType sessionType = SessionType.None;
public App()
{
UnhandledException += Application_UnhandledException;
InitializeComponent();
InitializePhoneApplication();
InitializeLanguage();
if (Debugger.IsAttached)
{
Application.Current.Host.Settings.EnableFrameRateCounter =true;
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
}
private void Application_Launching(object sender, LaunchingEventArgs e)
{
RemoveCurrentDeactivationSettings();
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
mustClearPagestack = CheckDeactivationTimeStamp();
if (!e.IsApplicationInstancePreserved)
{
RestoreSessionType();
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
SaveCurrentDeactivationSettings();
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
RemoveCurrentDeactivationSettings();
}
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
private void Application_UnhandledException(object sender,ApplicationUnhandledExceptionEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
private bool phoneApplicationInitialized = false;
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
RootFrame= new PhoneApplicationFrame();
RootFrame.Background = new SolidColorBrush(Color.FromArgb(255, 27, 200, 174));
RootFrame.Navigated += CompleteInitializePhoneApplication;
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
RootFrame.Navigated += CheckForResetNavigation;
RootFrame.Navigating += RootFrame_Navigating;
phoneApplicationInitialized = true;
}
void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (e.Uri.ToString().Contains(#"/MainPage.xaml") == true && !AppPrefManager.Instance.IsFastAppResumeEnabled)
{
RootFrame.Dispatcher.BeginInvoke(delegate
{
if (!AppPrefManager.Instance.IsVirginLaunchCompleted)
{
RootFrame.Navigate(new Uri(Constants.kIntroPage, UriKind.Relative));
}
else
{
RootFrame.Navigate(new Uri(Constants.kMainPage, UriKind.Relative));
}
});
e.Cancel = true;
}
if (sessionType == SessionType.None && e.NavigationMode == NavigationMode.New)
{
if (e.Uri.ToString().Contains("DeepLink=true"))
{
sessionType = SessionType.DeepLink;
}
else if (e.Uri.ToString().Contains("/MainPage.xaml"))
{
sessionType = SessionType.Home;
}
}
if (e.NavigationMode == NavigationMode.Reset)
{
wasRelaunched = true;
}
else if (e.NavigationMode == NavigationMode.New && wasRelaunched)
{
wasRelaunched = false;
if (e.Uri.ToString().Contains("DeepLink=true"))
{
sessionType = SessionType.DeepLink;
}
else if (e.Uri.ToString().Contains("/MainPage.xaml"))
{
if (sessionType == SessionType.DeepLink)
{
sessionType = SessionType.Home;
}
else
{
if (!mustClearPagestack)
{
e.Cancel = true;
RootFrame.Navigated -= ClearBackStackAfterReset;
}
}
}
mustClearPagestack = false;
}
}
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
if (RootVisual != RootFrame)
RootVisual = RootFrame;
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Reset)
RootFrame.Navigated += ClearBackStackAfterReset;
}
private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
{
RootFrame.Navigated -= ClearBackStackAfterReset;
if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
return;
while (RootFrame.RemoveBackEntry() != null)
{
;
}
}
private void InitializeLanguage()
{
try
{
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
RootFrame.FlowDirection = flow;
}
catch
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
throw;
}
}
bool CheckDeactivationTimeStamp()
{
DateTimeOffset lastDeactivated;
if (settings.Contains("DeactivateTime"))
{
lastDeactivated = (DateTimeOffset)settings["DeactivateTime"];
}
var currentDuration = DateTimeOffset.Now.Subtract(lastDeactivated);
return TimeSpan.FromSeconds(currentDuration.TotalSeconds) > TimeSpan.FromSeconds(30);
}
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
if (settings.Contains(Key))
{
if (settings[Key] != value)
{
settings[Key] = value;
valueChanged = true;
}
}
else
{
settings.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
public void RemoveValue(string Key)
{
if (settings.Contains(Key))
{
settings.Remove(Key);
}
}
public void SaveCurrentDeactivationSettings()
{
if (AddOrUpdateValue("DeactivateTime", DateTimeOffset.Now))
{
settings.Save();
}
if (AddOrUpdateValue("SessionType", sessionType))
{
settings.Save();
}
}
public void RemoveCurrentDeactivationSettings()
{
RemoveValue("DeactivateTime");
RemoveValue("SessionType");
settings.Save();
}
void RestoreSessionType()
{
if (settings.Contains("SessionType"))
{
sessionType = (SessionType)settings["SessionType"];
}
}
Suppose while I am in ThirdPage. I press the Windows button. And then I press my App icon from the start screen. Rather than the app resuming from the ThirdPage. It first shows the ThirdPage and then starts from the MainPage.
By default, the app still navigates to the default page, when the application is launched via the app tile.
You can check the session type in the RootFrame_Navigated methods and cancel that navigation, if you so wish.
The default template adds a CheckNavigation method to in the app.xaml.cs that clears the backstack after a navigation with NavigationMode Reset.
You can check there, if your app should stay on the last page or if it is better to reset and start over.
A sample for handling different activation types can be found here:
MSDN Fast Resume Sample, App.xaml.cs
(Method: RootFrame_Navigated)
Code as listed will mess up. It doesn't match the comments.
Look at the RootFrame_Navigating - mustClearPagesStack at the bottom is set to false - but look at the comments in the original MSDN link - two places above it say the page stack must be cleared.... but because the flag is set to false it's messed up. So set the flag false at the top, but then set it to true in the two 'if conditions' where it says to.
Then it will work like a champ.