CoreWindow::GetCurrentForThread() always NULL - windows-runtime

I'm trying to get the CoreDispatcher in C++ on Windows Phone 8 so that I can submit work items to the UI thread Dispatcher so I can update UI elements on the UI thread. However, when I call CoreWindow::GetCurrentForThread(), I get NULL back. In the documentation it states that this is supported on WP8. As long as I'm getting NULL for the current Window, I can't get the current Dispatcher from it; does anyone know how to get the current Dispatcher on WP8?

CoreWindow::GetForCurrentThread() is documented as returning:
The CoreWindow for the currently active thread.
If you call this function from a thread that does not have a CoreWindow (like any non-UI thread), then this function will return nullptr.
Assuming the application has finished initializing and there is a view, you can use the dispatcher from the main view of the application via CoreApplication::MainView. Alternatively, you can pass the Dispatcher^ for the UI thread to the code executing on the non-UI thread so that it has access to it when it needs to invoke back onto the UI thread.

I have used
await CoreApplication.Views.First().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//your code here
});

Related

What does `PluginUtilities` do in Flutter's `dart:ui` library, and how do I use it?

PluginUtilities is documented as "Functionality for Flutter plugin authors.". It's quite hard to understand what it does. When/ how should I use it?
PluginUtilities does two things:
You can pass these references between completely different isolates running different code. For example, you could implement a method in Isolate A, get a handle for it, pass the handle to Isolate B, get the method from that handle using PluginUtilities.getCallbackHandle, and call that method in Isolate B.
final handle = PluginUtilities.getCallbackHandle(myLovelyFunctionTearOff); // What is a tear off?: https://stackoverflow.com/questions/69065771/what-is-an-instance-method-tear-off
if (handle == null) {
// function has to be a static method or a top level function. It is null otherwise.
// TODO Show an error to the user to help them fix it.
}
Once you receive the handle in a separate isolate, you can get the function once again:
final function = PluginUtilities.getCallbackFromHandle(handle);
final result = function();
Examples of usage
Firebase messaging uses it twice, specifically for background messages. They use it for 2 functions:
They get a handle to the users callback function, that the user set.
final CallbackHandle userHandle = PluginUtilities.getCallbackHandle(handler)!;
They get a handle to their additional app entrypoint (main function, which they call _firebaseMessagingCallbackDispatcher ):
final CallbackHandle bgHandle = PluginUtilities.getCallbackHandle(_firebaseMessagingCallbackDispatcher)!;
They save these handles into SharedPreferences, and use them when the app is launched by a push notification. This is because the Flutter application doesn't automatically get launched in this case, on Android. The service or broadcast receiver is launched without an Activity, which launches the FlutterEngine and your app.
When this happens, Firebase_messaging will use these handles to get the callback function and app entrypoint, and launch them. So your callback still gets called when the your app is not running, because it runs a new application/ entrypoint (_firebaseMessagingCallbackDispatcher):
void _firebaseMessagingCallbackDispatcher() {
// Initialize state necessary for MethodChannels.
WidgetsFlutterBinding.ensureInitialized();
const MethodChannel _channel = MethodChannel(
'plugins.flutter.io/firebase_messaging_background',
);
// This is where we handle background events from the native portion of the plugin.
_channel.setMethodCallHandler((MethodCall call) async {
/** implementation of method call handling **/
});
// Once we've finished initializing, let the native portion of the plugin
// know that it can start scheduling alarms.
_channel.invokeMethod<void>('MessagingBackground#initialized');

ServiceLocationProvider is null when launched as a Share Target

I'm using MVVM Light and everything is fine except when launching my Windows Phone 8.1 WinRT app as a Share Target.
When I try to assign MainViewModel viewModel = ServiceLocator.Current.GetInstance<MainViewModel>(); I get an exception for ServiceLocator.Current.
Exception Message: ServiceLocationProvider must be set.
Do I need to do something extra in App.xaml.cs OnShareTargetActivated event to insure the Locator is running?
UPDATE:
A ShareTarget page needs to be thought of as a small extension of your app. It seems that not all of the app's resources are loaded (including app-wide resources in App.xaml). So I just created a new instance of MainViewModel in the share page's constructor, loaded only the things I need for the share to complete, save the information and call ShareOperation.ReportCompleted. This returns the user back to the app that is sharing.
I still haven't found a good solution for getting other resources in my ViewModel, but this works for now.
This indicates that the following line has not been executed:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
This line will instruct the ServiceLocator class to use the SimpleIoc.Default instance as its ServiceLocator.Current. When you run your app as a Share target, the initialization is slightly different and probably the ViewModelLocator doesn't get initialized. You need to find a good location to perform the initialization before you use the ServiceLocator.
Cheers
Laurent

Use MessageDialog/MessageBox with Portable Class Library and MVVM Light

I´m developing an App that will be available for Windows Phone 8 and the Windows Store. To reduce redundancy I´m using a Portable Class Library (PCL) and on top of that I'm trying to apply the MVVM pattern with the help of the MVVM Light PCL Toolkit. The ViewModels are placed in the PCL and are bound directly in the XAML of the Apps pages.
When the data is received without an error, everything works fine. But I don´t know how to get the exceptions/error message back to the App when errors do happen.
Inside the Windows Store App errors will show as a MessageDialog while the Wp8 App will use the MessageBox class. Obviously the PCL isn´t aware of any of these classes. What I´m not getting is how to know if a ViewModel ran into an error, and how to get the message inside the App. Is this even possible when the ViewModels are bound inside the XAML?
The code in the ViewModel (inside the PCL) looks like this:
DataService.Authenticate((token, error) =>
{
if (error != null)
{
// This is, obviously, not going to work.
MessageBox.Show(error.Message);
return;
}
Token = token;
});
So I have to save the error somehow and let the App itself know the error has occurred, and then call the matching way of showing the error to the user.
Currently I´m thinking of something like defining an Error-property inside the BaseViewModel and fill it when errors in the ViewModel occur. Then, in the CodeBehind of the pages, make them aware of the current ViewModel and bind a PropertyChanged-event to this Error-property. But I was not able to implement it yet, so I don't know if this is even the right way to go.
Do I have to step down from the idea to bind the ViewModels inside the XAML, and do I instead have to initialize them inside the pages Codebehind?
Your instinct is correct, but there are more than a few ways of going about this.
First and foremost, you can use Mvvm's Messaging library, which will allow your ViewModel to send messages directly to your View. Your View can then handle it in any way it wishes, including but not limited to using a MessageDialog.
Secondly, you can also create a Function or Action (likely the former) in your ViewModelLocator for ShowMessageDialog. This Function will likely take a string and return a Task. Then, after you initialize your ViewModelLocator initially, you can inject your ShowMessageDialog code. Your ViewModels can then use whatever platform's MessageDialogs that they please.
Ex:
Note: This code uses the BCL Async libraries that are accessible in Nuget. They work in the PCL just fine.
ViewModelLocator:
public static Func<string, Task> ShowMessageDialog { get; set; }
App.xaml.cs:
ViewModelLocator.ShowMessageDialog = (message) =>
{
// For Windows Phone
return TaskFactory.StartNew(() => MessageBox.Show(message));
// For Windows 8
MessageDialog md = new MessageDialog(message);
return md.ShowAsync().AsTask();
};
ViewModel:
await ViewModelLocator.ShowMessageDialog("This is my message.");
Secondary Note: The md.ShowAsync().AsTask(); must be run on the UI Thread. This means that you will have to invoke it via the dispatcher in the case that you are running it in a task asynchronously. This is possible using a similar method of injecting the use of the app's CoreDispatcher via the RunAsync method.
This means that you can, on any platform (Windows 8 and Windows Phone shown above), inject whatever Message Dialog system you want and use it in your PCL.
I would say that it is much easier to do the first method I suggested, as that is what it is there for, but the Function method version is definitely helpful at times.

win 8 app call back handler - waiting on a runasync operation C++

I have a win 8 application written in unmanaged c++/cx which has a callback handler. The call back handler posts a notification to a UI thread.
I want to wait on the UI dispatch handler's background task.
I have the following code -
dispatcher->RunAsync(Windows::UI::CoreDispatcherPriority::Normal,lambda);
In the lambda, I update a view model that is bound to my view. I want to wait on this operation and check on the view model. Is it possible in unmanaged c++ ?? It is part of the unit testing that am doing on the app.
I found code references to achieve this in C#. I am not familiar with C++/CX to get this done. I would like comments on ideas to accomplish this. Thank you so much!
regards,
Varsha

Execute Action on UI Thread Synchronously in WinRT

I'm developing some corss platform library, and need to execute a action on the UI thread.
Although I know there is a method Dispatcher.RunAsync can execute the action on UI thread, but it is async, and I can't use await/async feature becuase the code is corss platform and I don't want the library is bound to the await/async feature of .net 4.5.
Is there any way to execute the action on UI thread synchronously?
Thanks
A cross-platform library should not depend on a particular UI (e.g., Dispatcher or CoreDispatcher). There's a type that represents an abstract "context": SynchronizationContext; I wrote an MSDN article on the subject a while back.
If it is possible for your library to capture the UI context before it needs to use it, then you can capture SynchronizationContext.Current and later use Send to execute some code on the original context synchronously.
If you execute it from the UI thread - there is no way to do it. From a background thread you might do it for example using an AutoResetEvent that you wait for after calling RunAsync and setting it from the RunAsync callback.