I can't for the life of me get the following functionality to work:
User taps item
Item's image becomes visible via changing visibility property of image
After a short period of time image becomes invisible again (with no user input) via changing the
visibility property
Or, more simply:
Make visible UI change
Pause so user can see UI change
Reverse step 1's UI change
Step 2 happens before steps 1 and 3 regardless of where the code is because the UI is not updating until the logic finishes (I assume).
I am setting the visibility of the image via data binding with INotifyPropertyChanged. All works as expected except when I'm trying to introduce the pause.
I'm trying to pause with this simple method:
private void Pause()
{
new System.Threading.ManualResetEvent(false).WaitOne(1000);
}
It does pause, but the UI changes wait until after that pause even though a change to the bound data happen befores the pause is called, and the other change after.
I have tried using the dispatcher, but it doesn't change anything, and I don't understand it enough:
await dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
clickedCard.IsFaceDown = false; // makes the image visible via data binding
}
);
Pause();
I think I need to do something with threading, but I am going in circles.
Any ideas?
You should never do something like this inside the UI thread of your app:
new System.Threading.ManualResetEvent(false).WaitOne(1000);
There are various reasons for not doing it, but in your particular case the problem is that XAML only re-draws once your event-handler completes. So basically this happens:
The item is invisible
Your event handler is called
You set it to visible (but the UI doesn't refresh yet)
You freeze the thread for a second
You set it to invisible again
The event-handler completes
Now the UI updates based on the current value (which is invisible)
I suggest you look at building a Storyboard to do this - Blend can help. See here.
[Question]
On Windows Phone 8.1, what exactly happens in between the time when the user leaves the app and the OnSuspended event fires? I'm having trouble with the ability to manage objects in that span, in particular MediaCpture object.
To better explain the problem, here is the scenario:
The user is on a page with a video preview being pumped to a CaptureElement
The user taps the Start button
The user taps Back button and returns to the page with a broken MediaCapture
With WinRT there isn't an ObscuredEvent and OnNavigatingFrom doesn’t fire unless you’re going to another page in the same Frame. After some investigation, I've found that the only event that fires is Window.Current.VisibilityChanged
I've gone ahead and hook it when the page is NavigatedTo and unhooked in OnNavigatedFrom (see ex2 below). Inside the event, I check for parameter that tells if the app is hiding or showing and dispose/initialize accordingly(see ex.1 below).
[Problem]
However, this only works with the debugger attached. If I do this without the debugger attached, it doesn't reinitialize and frequently crashes the camera and I have to literally reboot the device.
Code Example 1 (note: e.Visible == false is leaving the app and true when returning)
async void Current_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
{
if (!e.Visible) //means leaving the app
{
await DisposeAll(); //cleans the MediaCapture and CaptureElement
}
else
{
if(mediaCaptureManager != null) await DisposeAll();
await Initialization(); //set up camera again
}
}
Example 2 (hooking into the event)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.navigationHelper.OnNavigatedTo(e);
}
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.VisibilityChanged -= Current_VisibilityChanged;
this.navigationHelper.OnNavigatedFrom(e);
}
[Update: Resolution]
Instead of using VisibilityChanged, hook into Window.Current.Activated on the page's constructor. With the debugger completely detached, the Activated event will provide the WindowActivationState parameter in the WindowActivatedEventArgs. Like this:
private async void CurrentOnActivated(object sender, WindowActivatedEventArgs e)
{
if(e.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//dispose MediaCapture here
}
else if(e.WindowActivationState == CoreWindowActivationState.CodeActivated || e.WindowActivationState == CoreWindowActivationState.PointerActivated)
{
//initialize MediaCapture here
}
}
See my answer in https://stackoverflow.com/a/28592882/3998132. Using Window.VisibilityChanged in conjunction with your Page\UserControl Loaded\Unloaded handler should solve your issue I believe.
Using Window.Activated is less desirable than Window.VisibilityChanged because Activated relates to being visible AND having focus where as VisibilityChanged only pertains to visibility. For showing a preview having focus is not applicable. Since Windows Store apps on Windows Phone can only have one Window showing there is no difference in using either however if your app becomes universal and runs on let's say on Windows 8+ Modern shell (which can show multiple Store apps with the Snap window feature) or Windows 10 desktop (which can support multiple Store apps showing at the same time) you will not want to stop preview when a user changes focus from your app but your app is still showing.
I'm not sure if it wouldn't be more suitable to use Suspending/Resuming events. Note only that in this case, you will have to debug it properly - it behaves little different while being run with/without debugger attached.
As for the code - hooking your event in OnNavigatedTo/OnNavigatedFrom is not a good idea - when the OS suspends the app and you are using SuspensionManager then OnNavigatedFrom will be called, but when you go back to your app (resume it), then OnNavigatedTo will not be called.
Using Window events may also work here, but why not subscribe it once, somewhere in constructor? - it's window-wide and hence in phone there is only one window, which stands for app, then subscribe once. In this case, you may add a line that recognizes the current page in window and if that page contains mediacapture then dispose (create similar). Then you can also dispose/initialize in navigation events in case user doesn't leave your app and just navigate.
In AS3, stage.focus get/sets the display object with the focus. Focus can be assigned to any InteractiveObject instance and anything inheriting from it, such as TextFields, Sprites, and MovieClips.
Incidentally, I looked to see if any of this was part of the ECMAScript spec (since AS3 and JavaScript have that in common) and learned that in JavaScript managing the focus (retrieving it in particular) is much more difficult; older browsers do not support the document.activeElement property, and even newer ones are restricted to returning input-related elements only. If no such element has the focus, all major browsers return the body element - except IE 9, which returns the html element, Chrome 26 returns false in XHTML documents, but apparently you can use document.querySelector(':focus').
In contrast to JavaScript, I discovered that AS3 is very uniform and consistent in that any InteractiveObject can receive the keyboard focus; however, objects (aside from TextField and SimpleButton instances) do not receive the focus via mouse or keyboard interaction by default.
When I first attached an event listener to the stage and listened for the FocusEvent.FOCUS_IN event, it did not fire when I clicked a MovieClip object that I had created on the stage, which led me to the conclusion that MovieClips/Sprites/InteractiveObjects do not receive the stage focus by default through clicking or tabbing.
Meanwhile, if I set either the tabEnabled or buttonMode properties to true, then the event fires when the object is clicked. Incidentally, the documentation for tabEnabled says that it's automatically true when Sprite.buttonMode is true, so tabEnabled seems to be the property of interest (also, buttonMode enables other features as well such as triggering click events when the enter or space keys are pressed when the object has the focus).
I was just wondering if tabEnabled is the correct way to ensure an interactive object receives the stage focus when clicked. Although the documentation for tabEnabled says it causes the object to be included in the [keyboard] tab ordering, it doesn't mention mouse interaction in particular nor does it mention any generic state like "can receive focus". It seems that any interactive object can be assigned the focus manually by setting stage.focus to that object.
Is it correct that InteractiveObject's "tabEnabled" property is the primary property that controls whether focus can be assigned through interaction via both the keyboard AND mouse?
In JavaScript, the HTML5 spec lays out a more complex series of conditions that must be met for an object to be considered "focusable": "An element is focusable if all of the following conditions are met: 1. The element's tabindex focus flag is set. 2. The element is either being rendered or is a descendant of a canvas element that represents embedded content. 3. The element is not inert. *The element is not disabled."
UPDATE: Upon closer inspection, although AS3 does not have a generic "enabled" property, it seems that "mouseEnabled" functions similarly, because when set to false, "the instance does not receive any mouse events (or other user input events like keyboard events)."
UPDATE to first update: The documentation is wrong by including the phrase "(or other user input events like keyboard events)", because focused objects still receive key down/up events despite mouseEnabled being set to false.
As you presumed, it's the tabEnabled property that need to be set to ensure that a InteractiveObject can gain the focus through user input, but for clarity sake, I'll expand a bit my answer :
Any InteractiveObject can have the focus, no matter it's properties. However, there is a few properties that determine how to get the focus, and where the focus is.
Stage.focus indicates which InteractiveObject has the focus, right now; This method is not read-only, and setting it switch the focus to the given InteractiveObject; It is useful to programmatically alter the way the focus is handled in your application.
InteractiveObject.tabEnabled enable the instance to receive the focus via user actions; meaning clicking, tabbing, and using the arrow keys. Note that this property doesn't allow the instance to recieve user inputs; it only allows the Stage to give the focus to this instance.
InteractiveObject.tabIndex permit to set the tab order through the animation. It applies to tabbing only; using the arrow keys ignore this.
InteractiveObject.mouseEnabled has no relation to focus. It allows the instance to recieve Mouse events.
To better understand how focus works in AS3, one could say that an object doesn't take the focus, it is given the focus. The focus is managed by the Stage, and tabEnabled is an indicator for the Stage to know if it should give the focus to an objet or not.
Addendum : The tabEnabled property is false by default because AS3 estimates that most InteractiveObject doesn't need the focus. After all, a objet can receive clicks without needing the focus.
I have already marked another post as the answer, but I just wanted to add some additional info.
FocusEvent.MOUSE_FOCUS_CHANGE and FocusEvent.KEY_FOCUS_CHANGE precede the FOCUS_IN and FOCUS_OUT events and are cancelable, unlike the FOCUS_IN/OUT events.
More importantly, both the target and related objects are populated (i.e. are non-null) in the MOUSE_FOCUS_CHANGE event, whereas the immediately following FOCUS_OUT event will have a null related object if the clicked object's tabEnabled value was false.
By handling MOUSE_FOCUS_CHANGE and KEY_FOCUS_CHANGE events in the capture phase on the stage, you can override the default behavior of the entire focus changing system, and even prevent the focus from ever becoming null as a result of a mouse click.
For example, the default behavior when clicking on an object (regardless of whether tabEnabled is true or false), is for a MOUSE_FOCUS_CHANGE event to be raised that includes the object that currently has the focus, as well as the clicked object. Then, conditionally:
If the clicked object has tabEnabled = true, then it will be assigned the focus, and the FOCUS_OUT/IN events will have both the target and related objects populated.
If, on the other hand, the clicked object has tabEnabled = false, then the focus is set to null, and the FOCUS_OUT event will have a null related object.
Therefore, if you cancel the default behavior that depends on the value of tabEnabled, you can just opt to always manually assign the focus to the related object in spite of tabEnabled being false, so mouse clicks will still trigger FOCUS_OUT events, but they'll never have a null related object.
Similarly, you can override the default behavior for keyboard-instigated focus changes. My KEYBOARD_FOCUS_CHANGE event handler is based in a class that maintains a pushable/popable stack of custom focus loop Arrays, so that when tab is pressed, it checks whether the currently focused object is in the active loop at the top of the stack (or is a child/grandchild of an object in the active loop), and if so, it assigns focus to the object at the next index position (or previous one if the shift key is down). If the object is not in the loop, it (based on a setting) automatically assigns focus to the first object in the active loop that happens to be at the top of the stack. It can even prevent focus from leaving the loop (focus object must be in the loop or a descendent of an object in the loop). The loop can be altered through public methods and can be assigned predefined sets of controls as dialog windows with different sets of controls are opened and closed. When you push a new Array of controls onto the stack for a dialog window, it backs up the currently focused object and current focus array, then moves focus into the new array. When you pop the stack, it restores the old array and returns focus to the object that had the focus when it was backed up. It all works very well, and is far more precise and controllable than the default mechanism.
The focus manager I've built even has a "nullFocus" property, which allows you designate a particular object as the object that should have the focus when the focus would otherwise become null, ensuring the focus is never actually null and events are always processable.
I know this is an old question, but I've been investigating the focus switching for some time now since a client had a novel request. They wanted the + key on the numpad to act like tab and change focus between text boxes.
How I accomplished it was through some trickery I established in my early programming days.
I wrote a function that generates text boxes (below):
function mkText(xpos,ypos,h,w,l:int,multi,sel,bor:Boolean,borCol:uint):TextField{
var textInput = new TextField();
textInput.x = xpos;
textInput.y = ypos;
textInput.height = h;
textInput.width = w;
textInput.maxChars = l;
textInput.multiline = multi;
textInput.selectable = sel;
textInput.border = bor;
textInput.borderColor = borCol;
addChild(textInput);
return textInput;
}
With this, I can create text fields in a loop with an array, such as this:
for(var i:int=0;i<8;i++)
{
cForm[i] = mkText(cFormXpos,cFormYpos,27,69,2,false,true,true,0x000000);
cForm[i].type = TextFieldType.INPUT;
cForm[i].restrict = "0-9";
cForm[i].defaultTextFormat = txFormat;
cFormYpos += cForm[i].height + 13;
}
Each run of the loop will create a new text field with a dynamically assigned instance name, which you can check if you trace the name of any element of the array, for example, instance1, instance2, etc. Each of those can be referenced by their array position as well and even batch formatted or referred to individually. With that approach, I used an incrementer and the general stage.focus attribute to switch between them.
function keyBind(e:KeyboardEvent)
{
if(e.keyCode == 107)
{
stage.focus = cForm[tabOrder];
if(tabOrder < 8)
{
tabOrder++;
}
else
{
tabOrder = 0;
}
}
}
I realize it's a somewhat crude solution to a more complicated issue, but the assigned indices make it easier to achieve tab-esque handling.
I hope this helps.
Cheers
ps. sorry for any subtle spelling errors. I typed this out quite quickly and had to edit a few times.
I go this response in Certification report:
The app does not appear to fully support touch input. The various
tiles on the main screen respond to touch/clicks but do not launch an
action. Touch support in this app do not appear to work to our
reviewers. Please see:
http://msdn.microsoft.com/en-us/library/windows/apps/Hh761498.aspx for
some of the common interactions for keyboard, mouse and touch.
This has never been an issue while developing and testing on several desktop computers and Surface RT. Any ideas on what might be the cause, or how I might reproduce it? The actions mentioned are hooked up to event handlers in code behind and use the navigation model with view models as parameters. I can post an example if needed, but there is nothing special in that code. What could cause a event-bound button to appear to be pressed but not call the handler, on some environments?
Extracts from one of the main features that the testers mention as non-functional:
View:
<GridView ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemClick="ItemView_ItemClick"..
Code behind:
void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
var foodItem = (FoodItemViewModel)e.ClickedItem;
var mainViewModel = (MainViewModel)this.DefaultViewModel["MainViewModel"];
mainViewModel.CurrentItem = foodItem;
this.Frame.Navigate(typeof(ItemDetailPageReadOnly), (MainViewModel)mainViewModel);
}
From ItemDetailPageReadOnly:
protected override void LoadState(Object navigationParameter,
Dictionary pageState)
{
if (pageState != null && pageState.ContainsKey("SelectedItem"))
{
navigationParameter = pageState["SelectedItem"];
}
var mainVm = (MainViewModel)navigationParameter;
this.DefaultViewModel["MainViewModel"] = mainVm;
this.DefaultViewModel["Item"] = mainVm.CurrentItem;
}
I would expect a NullPointerException if any of the parameters were null, not the described behavior from the testers.
you should use one of the higher level events unless you need to respond to a specific portion of the gesture. http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994936.aspx
I built a simple hello world app to check out the Flash Builder 4.5 mobile capabilities.
Here's how it works:
The Default View asks for name in an textinput and has a continue button
When you click the continue button it pushes a new view in the viewNavigator which just displays "Hello " + name in a label.
When you click anywhere in this view, it pops a view (i.e. itself) from the viewNavigator, to go back to the default view
I see only 1 issue with this:
When I get back to the default view, it is in its initial state, i.e. the textInput is blank. It seems as if the viewNavigator created a new view of the default view's class and pushed this, instead of just removing the top view and displaying the previous one.
I see this being especially problematic for programs which display data in a grid and you can click the data to view the detail...when you get back, the grid will be empty.
Any ideas or gotchas to solve this?
EDIT:
Project name: HelloWorld
Code below:
HelloWorldDefaultView.mxml
protected function button1_clickHandler(event:MouseEvent):void {
navigator.pushView(HiView, tName.text);
}
HiView.mxml
protected function view1_clickHandler(event:MouseEvent):void {
navigator.popView();
}
protected function view1_creationCompleteHandler(event:FlexEvent):void {
lblHello.text="Hello " + data;
}
Screenshots
Initial screen
Screen 2
Clicking on screen 2 gets us back to initial screen. Notice the blank textInput
Have you tried to set destructionPolicy="never" and then
protected function button1_clickHandler(event:MouseEvent):void {
data = tName.text;
navigator.pushView(HiView, tName.text);
}
to store the data in current View's data - before changing to another one?
That's the way it is supposed to work for mobile applications.
Check out this article: Flex 4.5 (Hero) – Persistant Data in MobileApplication
As they write:
Each time a View is removed from the display list (via popView() or pushView()) its instance is destroyed, but its data model is stored in memory.
In order to save session state for a View, you must modify the data property. This property will be requested when destroying the current instance of the View class. And the data property value will be assigned back to a newly created instance of the same View class when navigating back to that view.