CustomMessageBox: how to use with a ListPicker in PickerMode.Expanded? - windows-phone-8

I tried to use the CustomMessageBox with a listpicker in PickerMode.Expanded but I'm having problems.
The same problems can be seen running the CustomMessageBoxSample after changing the ItemsSource = new string[] { "5 minutes", "10 minutes", "1 hour", "4 hours", "1 day", "2 days", "10 day" } , that is with more than 5 elements so it will open in FullMode by default.
In this case, leaving the other code example as it is, clicking the listpicker opens the fullMode selecting page but, after a selection, the whole CustomMessageBox is closed (you cannot decide to press its left or right button).
I tried to change the code as follows, but in this case the fullMode selecting page is opened behind the messageBox and cannot be seen and no selection can be done (you can see it, in greyed, if you put many items so it has a long list of items so some of them can be displayed in background below the foreground messagebox.
messageBox.Dismissing += (s1, e1) =>
{
//if ((listPicker.ListPickerMode == ListPickerMode.Expanded)
if ((listPicker.ListPickerMode == ListPickerMode.Expanded) || (listPicker.ListPickerMode == ListPickerMode.Full))
{
e1.Cancel = true;
}
};
I tried also with the following code but the fullMode selecting page, even though is now visible, it is not enabled, so no selection can be done ....
messageBox.Dismissing += (s1, e1) => {
if (listPicker.ListPickerMode == ListPickerMode.Expanded)
{
e1.Cancel = true;
}
else if (listPicker.ListPickerMode == ListPickerMode.Full)
{
e1.Cancel = true;
messageBox.Visibility = Visibility.Collapsed;
//listPicker.IsEnabled = true; //???
// listPicker.Focus(); //???
// listPicker.UpdateLayout(); //???
}
};
listPicker.SelectionChanged += (s3, e3) => {
if (listPicker.ListPickerMode == ListPickerMode.Full) {
messageBox.Visibility = Visibility.Visible;
}
};
Any suggestion?
Thanks
Enzo Contini

Related

Weird error AS3. Term undefined

so I'm getting an error at line 342 which is
myTextField.text = object[curPart]["text"]
it says that a term is undefined. Tracing curPart gives me a null value, although in code that runs literally moments for that one, curPart is part3. Nothing changes it. This is what runs before it, a type writing effect function.
private function addCharackter():void
{
if (!textFinished)
{
// add the charackter to the Textfield
myTextField.text = object[curPart]["text"].substring(0,counter)
counter++
trace(curPart) // prints "part3"
// if you reached the end of the String stop Timer
if (counter == object[curPart]["text"].length+1 && !textFinished)
{
textFinished = true;
trace("Text finished:",textFinished)
clearInterval(sInt)
counter = 0;
if (object[curPart]["text"].indexOf("What do you do?") >= 0)
{
trace("H!!!")
choosing = true
createOptions();
}
if (object[curPart]["text"].indexOf("What do you do?") >= 0)
{
dead = true;
}
}
}
Another weird thing is that the error doesn't happen if I finish the type writing effect by pressing space which is done here:
public function onEnter(key:KeyboardEvent):void
{
if (key.charCode == 32)
{
if (dead && textFinished && !choosing)
{
curPart = object[curPart]["lastPart"]
textFinished = false
dead = false;
myTextField.text = ""
counter = 0;
sInt = setInterval(addCharackter, textSpeed)
}
if (!textFinished && !choosing && !dead)
{
trace(textFinished)
trace("finishing")
trace(curPart)
myTextField.text = object[curPart]["text"]
if (object[curPart]["text"].indexOf("What do you do?") >= 0)
{
trace("H!")
choosing = true
createOptions();
}
if (object[curPart]["text"].indexOf("You have died") >= 0)
{
dead = true;
}
clearInterval(sInt)
textFinished = true;
}
else if (textFinished && !choosing && !dead)
{
trace("Hi!!!!")
curPart = object[curPart]["nextPart"]
myTextField.text = ""
counter = 0;
sInt = setInterval(addCharackter, textSpeed)
textFinished = false
}
}
}
I've looked through my code for hours. text is inside part3 and part3 DOES exist, considering it works if I skip the typing process by pressing space. (it also doesn't happen if I were to skip the typing process before part3.)
edit: Another thing that I just realised, line 342 should never be ran because textFinished should equal true (which it is moments before, but when I press space, it magically isn't. I don't change it to false anywhere except in parts that aren't running when the error happens)
Never mind. Found why it wasn't working. Stupid user error.

Get first visible item in a GridView/ListView

I'm showing a set of pictures in a page. I use a GridView to show the pictures. However, when the user resizes the screen to make it narrow, I switch to a ListView.
The problem now is synchronizing the scroll position for the two lists. My approach to the solution is,
1. Get the first visible item of the first list.
2. Scroll the second list to that item using ScrollIntoView
However I'm unable to see any property in GridView/ListView that gives me the first information. Any ideas?
Also any other ways of doing this are appreciated.
That seems to be just about the way I would first try to do it. You can use the ItemsPanelRoot property of the GridView/ListView and get the Children of the panel, then use TransformToVisual().TransformPoint() relative to the list control on each child to find the first one that is visible.
The one gotcha I can think of is when ScrollIntoView() would scroll the item that was first in view port in one list to show as last in view in the other one. Maybe you could get the ScrollViewer from the template of the list control (e.g. by using VisualTreeHelper) and scroll to the beginning of the list first?
The most simple way to do it all might be to just scroll to the same relative offset in the list coming into view as the one going out. It might not be very precise, but it could work.
You could even do a nice animated transition of elements in one list into the elements in the other one.
*Update
I asked around and it seems like I forgot that the default panels in GridView and ListView - the ItemsWrapGrid and ItemsStackPanel contain a FirstVisibleIndex property that could be used to get the object and then call ScrollIntoView() on the list control, which in turns takes a ScrollIntoViewAlignment enum you can use to say you want the scrolled-to-item to be the first visible (aligned to the leading edge).
*Update 2
For ListViewBase - you can also use the ListViewPersistenceHelper to get and set relative offsets.
This upcoming update to WinRT XAML Toolkit might be helpful as it would allow you to simply call: gridView.SynchronizeScrollOffset(listView); or vice versa.
public static class ItemsControlExtensions
{
public static ScrollViewer GetScrollViewer(this ItemsControl itemsControl)
{
return itemsControl.GetFirstDescendantOfType<ScrollViewer>();
}
public static int GetFirstVisibleIndex(this ItemsControl itemsControl)
{
// First checking if no items source or an empty one is used
if (itemsControl.ItemsSource == null)
{
return -1;
}
var enumItemsSource = itemsControl.ItemsSource as IEnumerable;
if (enumItemsSource != null && !enumItemsSource.GetEnumerator().MoveNext())
{
return -1;
}
// Check if a modern panel is used as an items panel
var sourcePanel = itemsControl.ItemsPanelRoot;
if (sourcePanel == null)
{
throw new InvalidOperationException("Can't get first visible index from an ItemsControl with no ItemsPanel.");
}
var isp = sourcePanel as ItemsStackPanel;
if (isp != null)
{
return isp.FirstVisibleIndex;
}
var iwg = sourcePanel as ItemsWrapGrid;
if (iwg != null)
{
return iwg.FirstVisibleIndex;
}
// Check containers for first one in view
if (sourcePanel.Children.Count == 0)
{
return -1;
}
if (itemsControl.ActualWidth == 0)
{
throw new InvalidOperationException("Can't get first visible index from an ItemsControl that is not loaded or has zero size.");
}
for (int i = 0; i < sourcePanel.Children.Count; i++)
{
var container = (FrameworkElement)sourcePanel.Children[i];
var bounds = container.TransformToVisual(itemsControl).TransformBounds(new Rect(0, 0, container.ActualWidth, container.ActualHeight));
if (bounds.Left < itemsControl.ActualWidth &&
bounds.Top < itemsControl.ActualHeight &&
bounds.Right > 0 &&
bounds.Bottom > 0)
{
return itemsControl.IndexFromContainer(container);
}
}
throw new InvalidOperationException();
}
public static void SynchronizeScrollOffset(this ItemsControl targetItemsControl, ItemsControl sourceItemsControl, bool throwOnFail = false)
{
var firstVisibleIndex = sourceItemsControl.GetFirstVisibleIndex();
if (firstVisibleIndex == -1)
{
if (throwOnFail)
{
throw new InvalidOperationException();
}
return;
}
var targetListBox = targetItemsControl as ListBox;
if (targetListBox != null)
{
targetListBox.ScrollIntoView(sourceItemsControl.IndexFromContainer(sourceItemsControl.ContainerFromIndex(firstVisibleIndex)));
return;
}
var targetListViewBase = targetItemsControl as ListViewBase;
if (targetListViewBase != null)
{
targetListViewBase.ScrollIntoView(sourceItemsControl.IndexFromContainer(sourceItemsControl.ContainerFromIndex(firstVisibleIndex)), ScrollIntoViewAlignment.Leading);
return;
}
var scrollViewer = targetItemsControl.GetScrollViewer();
if (scrollViewer != null)
{
var container = (FrameworkElement) targetItemsControl.ContainerFromIndex(firstVisibleIndex);
var position = container.TransformToVisual(scrollViewer).TransformPoint(new Point());
scrollViewer.ChangeView(scrollViewer.HorizontalOffset + position.X, scrollViewer.VerticalOffset + position.Y, null);
}
}
}

Out of memory - 15+ PivotItems in PivotControl

I have a pivot control that its ItemsSource is databound to a collection of items.
The collection can be up to 50 items, so it means that it can be up to 50 PivotItems.
Each PivotItem contains Image control and some text controls.
After swiping between the pivot pages (about 15), when pressing the back button, the app crashs with "Out of Memory" exception.
Ofcourse the problem is in the PivotItems that takes all the memory each time I swipe to a new one.
I know the guildlines not recommend to use pivot with more than 6-7 items, but I really need it that way.
I saw some answer on the web that advices to use ContentControl with Content binded to my item layout as Resource.. but I find it hard to Implement.
Any more suggestions how to achieve the desirable result (no memory overflow)?
Thanks!
Edit:
I tried to manipulate the items by taking only 3, the current, the next and the previous.
But the behavior of the pivot is not good.. How should I increment/decrement the Pivot.SelectedIndex?
private void GestureListener_Flick(object sender, FlickGestureEventArgs e)
{
if (e.Direction.ToString() == "Horizontal") //Left or right
{
var itemVM = this.DataContext as ItemViewModel;
int i = pivot.SelectedIndex;
ObservableCollection<Item> items = new ObservableCollection<Item>();
var currentItemIndex = itemVM.CurrentReader.Reader.Items.IndexOf(itemVM.SelectedItem);
if (e.HorizontalVelocity > 0) //Right
{
currentItemIndex++;
}
else //Left
{
currentItemIndex--;
}
if (itemVM.AllItems.Count >= 3)
{
if (currentItemIndex == 0) // in case we are in the first item m in the AllItems collection.
{
items.Add(itemVM.AllItems[itemVM.AllItems.Count - 1]);
items.Add(itemVM.AllItems[currentItemIndex]);
items.Add(itemVM.AllItems[currentItemIndex + 1]);
}
else if (currentItemIndex == itemVM.AllItems.Count - 1) // in case we are in the last item in the AllItems collection.
{
items.Add(itemVM.AllItems[currentItemIndex - 1]);
items.Add(itemVM.AllItems[currentItemIndex]);
items.Add(itemVM.AllItems[0]);
}
else
{
items.Add(itemVM.AllItems[currentItemIndex - 1]);
items.Add(itemVM.AllItems[currentItemIndex]);
items.Add(itemVM.AllItems[currentItemIndex + 1]);
}
}
else // in case we have only 3 items, no manpulation needed.
{
items = itemVM.AllItems;
}
itemVM.CurrentItemsCollection = items; // only 3 items
}
}

Tabbing through a textarea that captures tab

Many times when I am being tab to switch fields, some times it entered into a text area where pressing tab indent your text. How can I get out these textareas using keyboard so I can continue switching fields.
...here is a fiddle that does the same.
If the websites themselves are overriding this default/expected behaviour then they are breaking a standard UI feature (and possibly lessening site accessibility - although that may depend on the particular application) and it is really up to the site to implement some kind of alternative. There is no other "built-in" keyboard shortcut to move focus to the "next page element".
If, however, you just want to get focus out of that textarea, then you could perhaps use another shortcut, such as Ctrl+L which moves focus to the address bar. From their you can start TABing again to move focus.
You can use the following to do what you need:
http://postcode.cf/support-tabs-in-text-areas.html
/* Support Tabs within your textarea */
HTMLTextAreaElement.prototype.getCaretPosition = function () { //return the caret position of the textarea
return this.selectionStart;
};
HTMLTextAreaElement.prototype.setCaretPosition = function (position) { //change the caret position of the textarea
this.selectionStart = position;
this.selectionEnd = position;
this.focus();
};
HTMLTextAreaElement.prototype.hasSelection = function () { //if the textarea has selection then return true
if (this.selectionStart == this.selectionEnd) {
return false;
} else {
return true;
}
};
HTMLTextAreaElement.prototype.getSelectedText = function () { //return the selection text
return this.value.substring(this.selectionStart, this.selectionEnd);
};
HTMLTextAreaElement.prototype.setSelection = function (start, end) { //change the selection area of the textarea
this.selectionStart = start;
this.selectionEnd = end;
this.focus();
};
var textarea = document.getElementsByTagName('textarea')[0];
textarea.onkeydown = function(event) {
//support tab on textarea
if (event.keyCode == 9) { //tab was pressed
var newCaretPosition;
newCaretPosition = textarea.getCaretPosition() + " ".length;
textarea.value = textarea.value.substring(0, textarea.getCaretPosition()) + " " + textarea.value.substring(textarea.getCaretPosition(), textarea.value.length);
textarea.setCaretPosition(newCaretPosition);
return false;
}
if(event.keyCode == 8){ //backspace
if (textarea.value.substring(textarea.getCaretPosition() - 4, textarea.getCaretPosition()) == " ") { //it's a tab space
var newCaretPosition;
newCaretPosition = textarea.getCaretPosition() - 3;
textarea.value = textarea.value.substring(0, textarea.getCaretPosition() - 3) + textarea.value.substring(textarea.getCaretPosition(), textarea.value.length);
textarea.setCaretPosition(newCaretPosition);
}
}
if(event.keyCode == 37){ //left arrow
var newCaretPosition;
if (textarea.value.substring(textarea.getCaretPosition() - 4, textarea.getCaretPosition()) == " ") { //it's a tab space
newCaretPosition = textarea.getCaretPosition() - 3;
textarea.setCaretPosition(newCaretPosition);
}
}
if(event.keyCode == 39){ //right arrow
var newCaretPosition;
if (textarea.value.substring(textarea.getCaretPosition() + 4, textarea.getCaretPosition()) == " ") { //it's a tab space
newCaretPosition = textarea.getCaretPosition() + 3;
textarea.setCaretPosition(newCaretPosition);
}
}
}

How do you create an if statement to check if many objects style == dispaly:none?

I'm making a memory-match game in which you flip two cards over in order to get them to match.
I'm doing it with simple if statements as shown below:
if(click == 2) //denotes two cards being clicked
{
if(flippedArray[1].src === flippedArray[0].src) // if click 1 == click 2 then refer to function 'delayMatch' which sets click 1 and 2 cards to not be displayed
{
window.setTimeout(function() { delayMatch() }, 500);
console.log("EQUAL");
score = +25000;
}
else
{
window.setTimeout(function() { delayNoMatch() }, 500); // if click 1 != click 2 then display card.png
console.log("NOT EQUAL");
score = -1999;
}
function delayMatch() //function for matching pairs
{
flippedArray[0].style = "display:none;";
flippedArray[1].style = "display:none;";
}
function delayNoMatch() //function for non-matching pairs
{
flippedArray[0].src = "card.png";
flippedArray[1].src = "card.png";
}
click = 0; // when clicked two cards set click back to zero
}
As you can see if two cards match they're set to display:none. What I'm trying to do is link to an "end game" html page once all 36 divs are set to display: none or I guess once the function delayMatch() has been called 18 times.
I'm completely at a loss as how I can do this.
my goal is something like this:
flippedArray[0] and flippedArray[1] is just a temporary array to check if the two cards currently in play are a match or not.
I was thinking something like:
endGameCounter =0;
endGameCounter++; //in the matching if-statement
then if(endGameCounter == 18)
{
location.href='link here'
}
You can use one variable for count inside the page.
If you are doing it in JSP, JSTL can help you here.
use to set a variable and just check the value time to time.
c:set var="COUNT" value="SOMETHING"/>
Try
function GameIsOver(){
for (var i = 0; i < allCards.length; i++) {
if(allCards[i].style.display === 'none')return false;
}
return true;
}