i would like to know if it is possible to refresh date time when the app returns from a deactivated state in WP7.5. My app is basically a calendar type and when the app starts the current day is highlighted.
So if i start the app, then press the start button, my app goes to deactivated state, then go to settings and change the time zone, naturally the date and time may change and then come back to my app, it retains the old date.
eg.
Suppose current date is 20 and we change the timezone where the date is 19, ideally my app should highlight 19, but it does not. I assume that its becomes before the app goes into deactivated state, it stores all the states and when it returns, it loads the same data. Is there anyway i could refresh the datetime?
Alfah
It's been a while since I've done any WP7 development, but I'm sure there's an event raised when the app is reactivated - can't you just query DateTime.Now or DateTime.Today at that point?
EDIT: Looking at the docs, I think you want the Launching and Activated events. (Launching so that you check the time even on the initial launch; Activated for reactivation after becoming dormant.)
Assuming that you have a model class that contains a DateTime field called DateToDisplayAsToday, and that model is accessible within App.XAML, you will want to to the following in App.xaml.cs
private void Application_Launching(object sender, LaunchingEventArgs e)
{
// Application_Launching fires when the app starts up.
// retrieve any data you persisted the last time the app exited.
// Assumes you have a local instance of your model class called model.
model = new model();
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
// Application_Activated fires when you return to the foreground.
// retrieve any data you persisted in the Application_Deactivated
// and then you can set the current DateTime
model.DateToDisplayAsToday = DateTime.Now;
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
// persist an data you don't want to lose during tombstoning
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
// persist any data you want to keep between separate executions of the app
}
Related
Hello drag and drop fans,
Can anyone explain why I see a long lag time when using drag and drop with my UWP apps?
I wrote a test app that contains just the drag and drop message handlers and also the pointer handlers for comparison. Here’s the code...
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
grid1.AllowDrop = true;
grid1.DragOver += Grid1_DragOver;
grid1.Drop += Grid1_Drop;
grid1.DragLeave += Grid1_DragLeave;
grid1.PointerEntered += Grid1_PointerEntered;
grid1.PointerExited += Grid1_PointerExited;
}
// Drag Handlers ************************
private void Grid1_DragOver(object sender, DragEventArgs e)
{
msgFromPointer.Text = " drag/drop item has entered";
e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
Debug.WriteLine("in grid1 drag over handler");
}
private void Grid1_DragLeave(object sender, DragEventArgs e)
{
msgFromPointer.Text = "";
}
private void Grid1_Drop(object sender, DragEventArgs e)
{
Debug.WriteLine("in grid1 drop handler");
}
// pointer handlers *******************
private void Grid1_PointerEntered(object sender, PointerRoutedEventArgs e)
{
msgFromPointer.Text = "POINTER has entered";
}
private void Grid1_PointerExited(object sender, PointerRoutedEventArgs e)
{
msgFromPointer.Text = "";
}
When doing a drag and drop to my app, there seems to be about a 1/2 second delay before my app receives the dragOver message. In comparison, the pointerOver message seems to arrive almost simultaneously with the pointer movement. The slow behavior is the same when using the touch screen or a mouse. Here’s a video of the behavior…
video of the laggy behavior
The PC I’m using has a touch screen and I’m wondering if there is some sort of touch “driver” or filter that is slowing down the drag and drop message. I've tried a bunch of Windows config settings, like mouse and display settings, but no change. The PC is a Dell Inspiron 3593, with the latest drivers. My Windows 10 version is 1903, build 18362.836
The app I’m developing uses a lot of drag and drop and this slow behavior makes the user interface really difficult. It’s kind of like trying to conduct a phone conversation with a 1/2 second delay.
Any ideas?
Dan
The DragOver event is triggered when the application determines that the element under the current pointer is a potential placement target.
This requires the pointer to hover for a period of time. This may be the reason for the delay you think.
You can try the DragEnter event, which is triggered earlier than DragOver.
Thanks
I have a Xamarin form map on my screen and I'm using PropertyChanged event to retrieve geolocation information from my server and display the proper pins on screen.
While coding the solution I noticed the PropertyChanged event is triggered multiple times (up to 10 times) with a single zoom or drag action on the map. This causes unnecessary calls to server which I want to avoid.
Ideally I want to make only one call to server when the final PropertyChanged event is called but I cant's find an easy solution to implement this.
At this point I've added a refresh button to my page that becomes enabled when a PropertyChanged event happens and I disable it after user uses the button.
Obviously this fixed the too many calls to server but made the solution manual.
I was wondering if there is a more elegant way to make the server call but do it automatically.
Thanks in advance.
I just test the PropertyChanged event on iOS side and it just triggered one time with a single zoom or drag action on the map.
While if it really triggered multiple times, you can use a timer to call the server when the final PropertyChanged event is called, for example:
public partial class MapPage : ContentPage
{
Timer aTimer;
public MapPage()
{
InitializeComponent();
customMap.PropertyChanged += CustomMap_PropertyChanged;
}
private void CustomMap_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (aTimer != null)
{
aTimer.Enabled = false;
aTimer.Stop();
aTimer.Close();
}
aTimer = new Timer();
aTimer.Interval = 1000;
aTimer.Enabled = true;
aTimer.Elapsed += ATimer_Elapsed;
aTimer.Start();
}
private void ATimer_Elapsed(object sender, ElapsedEventArgs e)
{
aTimer.Stop();
//do web request
Console.WriteLine(sender);
Console.WriteLine("CustomMap_PropertyChanged");
}
}
In the above code, I set the Interval = 1 second, that means in 1 second, whatever how many times PropertyChanged triggered, only the last call will trigger the ATimer_Elapsed function.
The Interval can be set to any value depending on your requirement.
I am trying to implement KVO bindings in a Xamarin Mac desktop app.
I have followed the docs, and it is working, but the bindings appear to trigger 2 change events each time!
If I create a KVO model with a binding like this...
private int _MyVal;
[Export("MyVal")]
public int MyVal
{
get { return _MyVal; }
set
{
WillChangeValue("MyVal");
this._MyVal = value;
DidChangeValue("MyVal");
}
}
And bind a control to it in Xcode under the bindings section with the path self.SettingsModel.MyValue
It all appears to work fine, the control shows the model value, changing the model value programmatically updates the control and changing the control updates the model value.
However, it runs the change event twice.
I am listening to the change so I can then hit an API with the value.
SettingsModel.AddObserver(this, (NSString)key, NSKeyValueObservingOptions.New, this.Handle);
Then later...
public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
{
switch (keyPath)
{
case "MyValue":
// CODE HERE THAT UPDATES AN API WITH THE VALUE
// But this handler fires twice.
break;
}
}
Im not sure if its Xamarin or XCode that is causing the double trigger.
Interestingly, if you don't specify the Xcode WillChangeValue and DidChangeValue methods, then it doesn't trigger twice - as though Xamarin has automatically triggered the change once. However, it no longer triggers a change when programmatically updating the model value...
[Export("MyVal")]
public int MyVal { get; set }
The above will work for the Xcode controls, they will update the model and trigger a change event.
But programmatically updating it
this.SettingsModel.MyVal = 1;
Does not trigger the change event.
It's very confusing, any idea on how to stop 2 change events firing, as I don't want to hit the API twice every time!
When it fires twice, the stack trace (abridged) for the first has...
MainViewController.ObserveValue
ObjCRuntime.Messaging.void_objc_msgSendSuper_IntPtr()
Foundation.NSObject.DidChangeValue(string forKey)
CameraSettingsModel.set_MyValue(int value)
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
Which looks fine, but the second...
MainViewController.ObserveValue
AppKit.NSApplication.NSApplicationMain()
AppKit.NSApplication.Main(string[] args)
MainClass.Main(string[] args)
Has no mention of the Setting Model triggering the event
You are hitting this - Receiving 2 KVO notifications for a single KVC change
and need to override AutomaticallyNotifiesObserversForKey it appears.
Cocoa is "doing you a favor" by sending the notifications for you, which is great except you have the managed version also sending notifications.
It looks something like this:
[Export ("automaticallyNotifiesObserversForKey:")]
public static new bool AutomaticallyNotifiesObserversForKey (string key) => false;
bool _checkValue;
[Export("CheckValue")]
public bool CheckValue
{
get { return _checkValue; }
set
{
WillChangeValue("CheckValue");
_checkValue = value;
DidChangeValue("CheckValue");
}
}
public override void ViewDidLoad ()
{
base.ViewDidLoad();
this.AddObserver("CheckValue", NSKeyValueObservingOptions.New, o =>
{
Console.WriteLine($"Observer triggered for {o}");
});
CheckValue = false;
}
It is work only one time, than event handler not work.I do not understand why?
private void ThisAddIn_Startup(object sender, System.EventArgs e) {
var folder = Globals.ThisAddIn.Application.Session.DefaultStore.
GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks);
foreach(Outlook.TaskItem item in folder.Items) {
item.BeforeDelete += BeforeDelete;
item.Save();
}
}
private void BeforeDelete(object item, ref bool cancel) {
MessageBox.Show("Удалено");
// Marshal.ReleaseComObject(item); must I do It?
}
The object that raises the event must be alive to raise the events. In you case you are setting an event sync on a local variable that gets garbage collected and hence does not raise the events anymore. Keep the object referenced on the global (class) level. It your case, it needs to be a list of TaskItem objects.
That being said, do not ever set event sinks on all items in a folder. You will kill Outlook. Since the user needs to select an item before attempting to delete it, process Explorer.SelectionChange event, clear the list of items, then set up event sinks on the items from the Explorer.Selection collection
In WP application we need to provide user option to lock app with password.
As I understand WP app lifecycle, I need to put navigation to LockPage in App.Application_Activated, App.Application_Deactivated and start page, but I can not use NavigationService in App class...
I do not want to put navigation code to lock page in each other pages, or there is no other options?
I writed own solution, but may be it is not so elegant as it could be.
App locking logic: User enable app locking with password, we handling Application_Deactivated and Application_Closing events in App class and marking app as locked if user enabled this option. Then, on each page we should put check: is app currently locked and if it is, we should navigate to AppLockedWithPasswordPage. On AppLockedWithPasswordPage we need to check user`s password, if it is correct call NavigationService.GoBack().
So we need to do 6 steps:
You should choose where to save IsAppCurrentlyLocked (bool flag), AppLockPassword (string) and IsUserEnabledAppLockWithPassword (bool flag). I had chosen IsolatedStorageSettings
Create AppLockedWithPassword page, where you need to show TextBox and Button, do not forget to provide option for user to reset AppLock of course with deleting app data
AppLockedWithPasswordPage should prevent BackButton navigation, so preventing it:
// AppLockedWithPasswordPage
protected override void OnBackKeyPress(CancelEventArgs e)
{
// Preventing back key navigation
e.Cancel = true;
}
Check password on button click
// AppLockedWithPasswordPage
private void UnlockAppButton_Click(object sender, RoutedEventArgs e)
{
if (PasswordBox.Password.Equals(IsolatedStorageSettings["AppLockPassword"]))
{
NavigationService.GoBack();
}
else
{
// Say user, that password incorrect, etc...
}
}
In App class find Application_Deactivated (to handle app minimizing (windows button)) and Application_Closing (to handle when user closing app) methods, we should mark app as locked if user enabled this option when this events happens
private void SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking()
{
if ((bool)IsolatedStorageSettings["IsUserEnabledAppLockWithPassword"])
{
IsolatedStorageSettings["IsAppCurrentlyLocked"] = true;
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking();
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking();
}
And final step, on all pages you want to lock you should add check in OnNavigatedTo method which will navigate to AppLockedWithPasswordPage if app is currently locked
// Create some class, like PagesUtils or so on with check method
private static Uri uriToAppLockedWithPasswordPage = new Uri("pathToAppLockedWithPasswordPage", UriKind.Relative);
public static void NavigateToAppLockedWithPasswordPageIfAppLocked(PhoneApplicationPage page)
{
if ((bool)IsolatedStorageSettings["IsAppCurrentlyLocked"])
{
page.NavigationService.Navigate(uriToAppLockedWithPasswordPage);
}
}
// In each page you want to lock add
protected override void OnNavigatedTo(NavigationEventArgs e)
{
PagesUtils.NavigateToAppLockedWithPasswordPageIfAppLocked();
base.OnNavigatedTo();
}
P.S. of course real code is much better, this is just simple example, I hope it will help you
You should add the check in the Application_Launching and Application_Activated events.
The launching event for when the app is first opened and the activated one for when the user returns to the app after having left to do something else.
Have these events both set a flag and have the base page that all your pages inherit from check for this flag when navigated to. The check should be for if the flag is set, if it is, show the login prompt and then clear the flag after successful password entry.
This approach will handle FAS, FAR & deep linking, in addition to starting the app normally.
Beware Some choosers will trigger the activated event when they return to the app. Add extra handling for these as appropriate / if necessary.
Why not create a start page where the passwords is entered?
For instances you have your MainPage.xaml, create a InsertPasswordPage.xaml reference it on WMAppManifest as the start page:
<DefaultTask Name="_default" NavigationPage="InsertPasswordPage.xaml" />
And insert all the password logic on the InsertPasswordPage.xaml, when the user successfully logins just navigate to your main page ;)
EDIT: As Gambit said if the user pressed the back button he will return to the insert password page, but you can solve this by removing from the backstack the page after the user logged in.