What the right time for registering listener for Share/Search charms - windows-8

I need to register different share charm listener for every page. I have 2 pages. I added following code in every one:
DataTransferManager.GetForCurrentView().DataRequested += App_DataRequested;
I added it in constructor of one page and in UserControl_Loaded event of another (first page just doesn't have UserControl_Loaded so why I added it directly to constructor). At the moment when second page tryting to load, I got exception:
WinRT information: An event handler has already been registered
Additional information: A method was called at an unexpected time.
Where should I place it and what is "right" time to do this??
Also it looks confusing that we have different DataTransferManager for every view, but only one is active at current time. Ever more, I noticed, if you add only one listener for first page, other pages will share this listener anyway. If I have only one shared listener for all pages, is it correct register it in app.xaml.cs?

The way I resolved this issue was to deregister the event in the onNavigatedfrom event as below:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested -= App_DataRequested;
base.OnNavigatedFrom(e);
}

In BasePage.cs in constructor I added
public BasePage()
{
if (!_isListenToDataRequested)
{
_isListenToDataRequested = true;
DataTransferManager manager = DataTransferManager.GetForCurrentView();
manager.DataRequested += AppDataRequested;
}
}
private async void AppDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
IShareable shareable = Frame.Content as IShareable;
if (shareable != null)
{
DataRequestDeferral deferral = args.Request.GetDeferral();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => shareable.AppDataRequested(sender, args));
deferral.Complete();
}
}
And all my pages look like
public sealed partial class ContentPage : IShareable
{
public void AppDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{...}
}

Another solution was run this as below
private DataTransferManager dataTransferManager;
Put this in page loaded event
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
{
this.dataTransferManager = DataTransferManager.GetForCurrentView();
this.dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested);
}));
And
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// Unregister the current page as a share source.
this.dataTransferManager.DataRequested -=
new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>
(this.OnDataRequested);
}

I'd suggest doing it in the navigating events, the OnNavigatingFrom event will be triggered before the OnNavigatingTo of the page you're going to so you won't have this problem.
protected override Task OnNavigatingTo(WinRTXamlToolkit.Controls.AlternativeNavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += dataTransfer_DataRequested;
return base.OnNavigatingTo(e);
}
protected override Task OnNavigatingFrom(WinRTXamlToolkit.Controls.AlternativeNavigatingCancelEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested -= dataTransfer_DataRequested;
return base.OnNavigatingFrom(e);
}
//Note: This is the WinRT Xaml Toolkit version of the events, but the standard events will work the same way.

Related

How can I load - inflate items to a Recycler view without locking the UI or showing a load icon?

I just want to be able to display a list of contacts (without even communicating to a server) just the way it is displayed on the "Contacts" native app on the phone.
I have like 1500 contacts and when I try to load the recycler view, all items at once, it lags a lot 2 - 3 seconds.
I've achieved loading more items but with a loading bar and thats not what I want.
I've already tried Threads, Executors, postOnUIThread(), handler.post() and even AsyncTask -> Override -> doOnBackground. Nothing works.
private class CustomTask extends AsyncTask<Void, Void, Void> {
int inserted;
#Override
protected Void doInBackground(Void... param) {
//Do some work
try {
lcf.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
((BaseActivity) lcf.getActivity()).showProgressDialog();
}
});
int currentSize = contactsLoaded.size();
for (inserted = 0; inserted < lcf.getController().getContacts().size() && contactsLoaded.size() < lcf.getController().getContacts().size(); inserted++) {
contactsLoaded.add(lcf.getController().getContacts().get(currentSize + inserted));
notifyItemRangeInserted(contactsLoaded.size() - 1, inserted);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void param) {
//Print Toast or open dialog
//notifyItemRangeInserted(contactsLoaded.size() - 1, 0);
if(!lcf.getController().isSelectedAffiliated()){
lcf.disclaimerLayout.setVisibility(View.VISIBLE);
}else{
lcf.disclaimerLayout.setVisibility(View.GONE);
}
lcf.isLoading=false;
((BaseActivity) lcf.getActivity()).hideProgressDialog();
}
}
That code lives within my adapter, "lcf" is a reference to the fragment. If I use the already loaded list saved on the controller (that I get from the fragment reference) and then just call notifyDataSetChanged() it LAGS like hell. So with this CustomTask I tried to load every item and notify it one by one to a Background task hoping it would make the items pop up quickly and sequentially without interfereing with the UI thread to not freeze the screen. It doesn't work. I am out of options now. I've tried everything.

Where should I unregister events in XAML Behavior?

In a XAML behavior class, where should be the best place to unregister events? Should I unregister it in Unloaded event or should I do it while Deteching?
public class ShowKeyboardOnFocusBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
AssociatedObject.GotFocus += AssociatedObject_GotFocus;
AssociatedObject.Unloaded += AssociatedObject_Unloaded;
}
private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
AssociatedObject.GotFocus -= AssociatedObject_GotFocus;
AssociatedObject.Unloaded -= AssociatedObject_Unloaded;
}
protected override void OnDetaching()
{
AssociatedObject.Loaded += AssociatedObject_Loaded;
AssociatedObject.GotFocus += AssociatedObject_GotFocus;
}
...
You should use OnDetaching to unregister your events. This method will always be called and it is the approach used in the official UWP Behaviors library from Microsoft (see for example EventTriggerBehavior).
It used to be an issue (that the associated object got unloaded but behaviors stayed in memory) but it is now accounted for right within the library, so you know for sure Detach will be called (you can see it yourself in the FrameworkElement_Unloaded method in Microsoft.Xaml.Interactivity.Interaction source code)

How to display Service text updates on Screen in Android?

I am creating an Android activity and starting a service from this activity using the following code. Now I want to display text "Hello user" from this service to screen, meaning service should trigger this display. I could use Toast.maketext.show but the display will disappear after couple of seconds.
new Thread(new Runnable() {
#Override
public void run() {
startAdapterIntent.setAction("START_ADAPTER");
startService(startAdapterIntent);
System.out.println("Thread2: Adapter Service started.");
}
}).start();
How do I do that?
I tried to use this link:
Making changes to Main Activity UI from thread in Service
and its (probably) parent link
http://developer.android.com/reference/android/app/Service.html
section "Remote Messenger Service Sample"
While using this second link, the onServiceConnected part of ServiceConnection doesn't seem to be working? Please help. Thank you.
From within your service you should create a handler that can be triggered by a timer task, the handler should be the one directly responsible of doing the communication with the currently active UI thread..an example would be
long delay = 3000;
long period = 3000;
TimerTask mDoTask = new TimerTask() {
#Override
public void run() {
xHandler.sendMessage(Message.obtain(xHandler, SOME_OPERATION));
}
};
mT.scheduleAtFixedRate(mDoTask, delay, period);
Handler xHandler=new Handler(){
#Override
public void handleMessage(Message message){
switch (message.what){
case SOME_OPERATION:
YourMethod();// in this method you can display your text
break;
}
}
};

CompositionTarget.Rendering doesn't like my event handler in XAML

I'm converting a Windows Phone 7 app to Windows Store, so I'm moving over to Xaml. I have a method that runs at a certain point to update the data on the screen. It either assigns or removes an event handler delegate to the CompositionTarget.Rendering event. The message I get is No overload for 'OnCompositionTargetRendering' matches delegate 'System.EventHandler' '
Here's what I have:
private void CheckCompleted()
{
Color completeColor;
if (this.DecryptedText.ToString().ToUpper() == this.ThisPuzzle.QuoteText.ToUpper())
{
// We're done!!! ...
CompositionTarget.Rendering -= this.OnCompositionTargetRendering;// new EventHandler(this.OnCompositionTargetRendering);
...
}
else
{
...
CompositionTarget.Rendering += this.OnCompositionTargetRendering;// new EventHandler(this.OnCompositionTargetRendering);
...
}
}
protected void OnCompositionTargetRendering(object sender, EventArgs args)
{
this.DisplayTime();
if (ThisPuzzle != null)
{
foreach (UIElement thisElement in Letters.Children)
{
...
}
}
}
If you check the documentation CompositionTarget.Rendering is of type EventHandler<object> in Windows Store apps and not of type EventHandler as in Silverlight.
This means you need to change the signature of your event handler accordingly to:
protected void OnCompositionTargetRendering(object sender, object args)

Silverlight & events

namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
datePicker1.SelectedDateChanged -= datePicker1_SelectedDateChanged;
datePicker1.SelectedDate = DateTime.Today;
datePicker1.SelectedDateChanged += datePicker1_SelectedDateChanged;
}
private void datePicker1_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("datePicker1_SelectedDateChanged");
}
}
}
Why message box appears?
datePicker1.SelectedDateChanged -= datePicker1_SelectedDateChanged;
//Defines you use the RemoveHandler function. you might want to remove event handlers during the application lifetime
datePicker1.SelectedDate = DateTime.Today;
// You are Assigning to Datepicker Selected date
datePicker1.SelectedDateChanged += datePicker1_SelectedDateChanged;
// the event handlers on the relevant object are ready for user-initiated events at run time.
So The Message Box Came .
Third Line You Have Call The Eventhadler That Y it will come