Can a UWP App Self Activate Its Window? - c#

public class MainViewModel MyViewModel : INotifyPropertyChanged
{
Window window { get; set; }
public MyViewModel()
{
window = Window.Current;
}
async void MyWebSocketService_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ActivateWindow"
ActivateWindow();
break;
}
}
void ActivateWindow()
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
window.Activate();
window.CoreWindow.Activate();
});
}
}
I'm trying to get a hidden or minimized UWP app to regain focus in the OS upon a WebSocket notification. This is the code I tried. It fires but nothing happens. Is there a way to achieve what I'm trying to do?

A UWP app cannot resume itself from minimized state because its execution state is suspended (and therefore can't run any code). The resume needs to be triggered externally, either by the user or by another running app, which can activate the suspended UWP app via any of the supported app activation APIs, for example doing a launch via protocol - as you have already figured out.

Related

Displaying a WPF window from an Installer class

I'm having a similar problem as this issue. I'm trying to display a WPF window from an Installer class from System.Configuration.Install. My window, corresponding to my software license manager window, should ideally pop up during or after the installation process to install the license as well. However, the installation finishes without the window ever showing and I'm not sure why.
Here is my code:
[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
public Installer1()
{
InitializeComponent();
}
// INSTALL EVENT //////////
public override void Install(System.Collections.IDictionary stateSaver)
{
StaThreadWrapper(() =>
{
LicenseActivationWindow activationWindow = new LicenseActivationWindow();
activationWindow.ShowDialog();
});
}
// Method to call the xaml in a thread safe way
private static void StaThreadWrapper(Action action)
{
var t = new Thread(o =>
{
action();
System.Windows.Threading.Dispatcher.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
// UNINSTALL EVENT //////////
public override void Uninstall(System.Collections.IDictionary stateSaver)
{
}
}
I had to add the StaThreadWrapper method to fix the "The calling thread must be STA, because many UI components require this." error from calling the wpf window directly from the installer thread and I'm no longer getting the error message but I'm also not getting the window to show up. I thought this would solve the issue like [1] but it didn't.
What am I doing wrong?
Displaying a window in a System.Configuration.Install.Installer is probably not a very good idea but if you still want to try it out, then create an Application class on the STA thread. Something like this:
var t = new Thread(o =>
{
var app = new System.Windows.Application();
app.Run(new LicenseActivationWindow());
});
t.SetApartmentState(ApartmentState.STA);
t.Start();

Xamarin Forms navigation not working as expected in debug mode

We are working on a xamarin forms app where INavigationService is used for navigating between pages. I found a strange observation that i haven't come across.
Observation 1: App is deployed in Emulator/simulator and debug mode is stopped.
=> Navigation is working as expected
Observation 2: App is tested while running i debug mode.
=> Navigation to few screens not happening until user clicks randomly on screen. i.e, when user navigates from ClassA to ClassB the control(code execution) is shifted from ClassA to ClassB but UI still shows ClassA and when user clicks on screen randomly it navigates to ClassB UI ,the method in which the Navigation code is written in ClassA doesn’t end until user click on screen.
Code:
Class A VM:
private async Task ContinueToNextPageCommandAsync()
{
IsBusy= true;
if (listofItems <= 0)
{
await DialogService.ShowAlertAsync("Warning");
return;
}
await NavigationService.NavigateToAsync(typeof(ClassBViewModel), parameter);
IsBusy= False;
return;
}
Class B VM:
public override async Task InitializeAsync(object navigationData1,
object navigationData2 = null, object navigationData3 = null)
{
try
{
IsLoadingText = true;
// Statements to be executed during class initiation
IsLoadingText = false;
}
}
Note: IsBusy=False in classA doesn’t gets triggered until user clicks on screen after navigation.

Stopping Background Task On Page Navigation Back

I'm working on a Xamarin.Forms project that supports iOS and Android devices, and I'm using the MVVM design pattern.
I have navigation root page that consists of a ListView, when item is selected on this ListView, I execute the following command to Navigate to item details view.
Page DetailsPage = new View.DetailsView(SelectedItemData);
await Navigation.PushAsync(DetailsPage);
Once this Details Page is opened, I start running a background task.
private void StartBackgroundTask(){
TimerBackgroundTask = new Timer((o) => {
Device.BeginInvokeOnMainThread(() => Update()); }, null, 0, 1000);
}
}
Which is based on this class
public class Timer : CancellationTokenSource
{
public bool IsDisposed { get; set; }
public Timer(Action<object> callback, object state, int dueTime, int period)
{
System.Threading.Tasks.Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
{
Tuple<Action<object>, object> tuple = (Tuple<Action<object>, object>)s;
while (!IsCancellationRequested)
{
await System.Threading.Tasks.Task.Run(() => tuple.Item1(tuple.Item2));
await System.Threading.Tasks.Task.Delay(period);
}
},
Tuple.Create(callback, state), CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
protected override void Dispose(bool disposing)
{
IsDisposed = true;
if (disposing)
{
Cancel();
}
base.Dispose(disposing);
}
}
Update function updates UI every 1 second.
Everything works fine and as it should, no issues here, however problems start to occur once I navigate back to root page, and back to details page - doing so twice causes the following error:
System.ArgumentException'jobject' must not be IntPtr.Zero. Parameter name: jobject
The problem stops occurring once the StartBackgroundTask gets disabled entirely from the code, so I believe that it is the one responsible for the error. Furthermore, I'm fairly convinced that this background task keeps on running somewhere in the thread even though I navigate back to the root page and I believe that if I could somehow dispose of the background task OnDissapearing event / navigation back button pressed, the error would no longer persist.
Unfortunately I have no idea how I how or even if its possible to somehow bind command to navigation back pressed event given my Views are bound to ViewModel.
Any tips would be greatly appreciated.
You can detect that a page is being dismissed by overriding OnDisappearing. In your DetailPage you could have something like this:
protected override void OnDisappearing()
{
TimerBackgroundTask?.Dispose();
base.OnDisappearing();
}

Something is blocking the call state listener to get called in android over AT commands

I have a strange problem. I'm using an android app as server and a WinForms application as client. They are both communicating over a TCP socket connection. I have following piece code in my App:
public class StateListener : PhoneStateListener
{
private readonly MainActivity _activity;
public StateListener(MainActivity activity)
{
_activity = activity;
}
public override void OnCallStateChanged(CallState state, string number)
{
base.OnCallStateChanged(state, number);
_activity.UpdateCallState(state, number);
}
}
private void UpdateCallState(CallState state, string number)
{
PhoneState = state.ToString();
}
And in a thread called from the MainActivity:
while (PhoneState == "Idle") { }
//some code
Now the WinfForms application is making calls over the phone with AT Commands.
When I trying to make a call directly over the phone (before the connection is established) the state listener works. When I'm doing this over AT commands within the application then the state does not change at all.
Could this be because of the while loop which blocks the method to be called or could this come from the AT command?
Thank you!

WPF maintain window size across multiple windows

I am developing a WPF application (using MVVM) which consists of several windows. All windows have the same dimensions specified and open at the centre of the owner screen. The user may also resize the windows. I now require 2 things.
To maintain the same size across all windows in case the user resizes any of the windows.
To maintain the same position across all windows in case the user drags any of the windows on the screen.
For example, consider the following workflow: MainWindow -> ChildWindow1 -> ChildWindow2. On a button click in the MainWindow, ChildWindow1 opens. On a button click in ChildWindow1, ChildWindow2 opens. The windows open on top of each other, and once you close a window, the previous window would be shown. Suppose the user now resizes ChildWindow2. I want the same to be reflected across MainWindow and ChildWindow1 as well, such that when the user closes ChildWindow2, ChildWindow1 would be of the same size as that of the resized ChildWindow2. This would give users the impression that they're working in the same window.
Also, if the user drags any of the Windows, I want the position of the parent windows to change and correspond to that of the child window.
How can I achieve both these things?
I would create a class where you can subscribe and invoke actions. This class can look something like:
internal class ActionService<T>
{
private static ActionService<T> instance;
private readonly List<ServiceAction<T>> registeredActions;
private ActionService()
{
registeredActions = new List<ServiceAction<T>>();
}
internal static ActionService<T> Instance()
{
return instance ?? (instance = new ActionService<T>());
}
internal void Subscribe(string actionName, Action<T> action)
{
registeredActions.Add(new ServiceAction<T>(actionName, action));
}
internal void Unsubscribe(string actionName)
{
registeredActions.RemoveAll(action => action.ActionName == actionName);
}
internal void Invoke(string actionName, T parameter)
{
foreach (ServiceAction<T> action in registeredActions.Where(action => action.ActionName == actionName).ToArray())
{
action.Action.Invoke(parameter);
}
}
private class ServiceAction<TSub>
{
internal ServiceAction(string actionName, Action<TSub> action)
{
ActionName = actionName;
Action = action;
}
internal string ActionName { get; private set; }
internal Action<TSub> Action { get; private set; }
}
}
In the constructor of each ViewModel you can call something like:
ActionService<Thickness>.Instance.Subscribe("SizeChanged", SizeChaned);
The second parameter is a function so you have to add the following to your ViewModel:
private void SizeChanged(Thickness thickness)
{
// Change the size to the passed value
}
Now if anyone changes the size of any window you can call:
ActionService<Thickness>.Instance.Invoke("SizeChanged", ACTUALSIZE_AS_THICKNESS);
You can use this ActionService anywhere you want to communicate over ViewModel- or Model-Borders.
The way I would approach this is using WPF Behaviors, which allow you to encapsulate UI-specific (i.e. non-View Modelish) behavior.
I don't know your exact requirements here (are these the only windows in the application? Are they always synchronized?) but the general approach would be to create a SynchronizedWindowBehavior which I would attach to the different Windows.
This behavior will access some sort of central WindowSynchronizationService, an event aggregator or singleton service (presumably registered in your DI container) which publishes decoupled events. Each instance of the behavior listens to the attached window's Move and Resize events and publishes an event on the aggregator. The other behavior instances consume this event and resize/move their attached windows accordingly.
Here's a good tutorial, both for defining Blend behaviors, hooking them up to a window, and also (specifically) listening to Window resize events: http://10rem.net/blog/2010/01/09/a-wpf-behavior-for-window-resize-events-in-net-35

Categories

Resources