I have a page with two text boxes, a check box and another two text boxes below at the bottom.
When I click on the check box, i want to set focus to the text box below it.
This works fine, the soft-keyboard appears and the screen scrolls up to reveal the text box above the keyboard.
However, if either TextBox1 or TextBox2 is currently in focus and the keyboard is already showing, setting focus from the CheckBox_Click event will reset the screen and it scrolls back down.
I'm guessing that the events clash with one another
- TextBox loses focus and hides the keyboard + scroll the screen back down
- TextBox got focus from outside and shows the keyboard (but doesn't scroll the screen up)
Can this be prevented somehow?
Here's a simplified version of the xaml and code
The xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Margin="0,100,0,0">
<TextBox x:Name="TextBox1" />
<TextBox x:Name="TextBox2" />
<CheckBox Content="Click Me" Click="CheckBox_Click" />
<TextBox x:Name="TextBox3" />
<TextBox x:Name="TextBox4" />
</StackPanel>
</Grid>
the code behind:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
TextBox3.Focus();
}
The problem you have is that the OS will try and move the page when the focus is on a control that isn't in a scrollable container and is obscured by the SIP.
I've worked around this by putting all the content in a ScrollViewer and adjusting the VerticalScrollOffset based on the selected control and if the SIP is shown or not. This was a lot of very messy, fiddely code. Ask yourself if the value of moving the focus is worth the effort before starting as there isn't a simple solution.
Related
I'm creating a UWP project. I have a main usercontrol and some sub-Usercontrols that i what to display depending on the user selection.
On top of the main usercontrol, i have some buttons with an image that the user can select to go from one panel to another :
On each sub-panel i also have buttons (one for comming back to main panel, etc...).
The whole panel display is managed by a IntToVisibilityConverter that translate the panel index into visibility and back and forth.
If i open the app with let say PanelIndex = 0, buttons on Panel 0 display correctly, but when I change PanelIndex to 1 -> button on panel 1 do not appear.
Now then, if I open it with PanelIndex = 1, buttons on panel 1 display correctly now, and then by coming back to panel 0 -> panel 0 button disappear.
does any one know why buttons can appear or disappear?
is it a normal behaviour? (and i'm missing something)
is there a way to fix it or at least force an invalidatevisual on the new displayed panel?
EDIT:
The button is like so
<Button x:Class="MyApp.UIElements.AnimatedButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.UIElements"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
xmlns:utils="using:MyApp.Utils"
Name="Control">
<Grid IsHitTestVisible="False">
<utils:LayoutTransformer x:Name="transformer">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image Source="/Resources/MyGif.gif"
IsHitTestVisible="False" />
</Grid>
</utils:LayoutTransformer>
<Image Source="{Binding ElementName=Control,Path=Image}"
IsHitTestVisible="False"
Margin="30" />
</Grid>
</Button>
the panel changing is done in the viewmodel using an int that sets the visibility of each panel accordingly. Nothing special about that.
I'll add that when the app is running, if a CTRL + X and re CTRL + V any button, it then shows up (hence the invalidatevisual hint).
Thank world
I have two buttons. One is an edit button that when clicked allows the editing of other objects on the page. My hope is to have the second button appear only once this "edit state" has been initiated. That part isn't very difficult. However, I don't want to just alter the 1st button's alignment from right to left to make space for the 2nd button (a cancel button) to the 1st button's right - I want to animate this movement, as if to make it appear that the moving of the 1st button to the left, is uncovering the 2nd button.
I've been searching for hours trying to find out how to do this, and there's a multitude of options for WPF, but not many solutions for UWP applications.
So far, I've found this:
<Button x:Name="EoIdButton" Grid.Row="0" Grid.Column="2" view:EventHandlers.Attach="Click" BorderBrush="DarkGray" FontFamily="Segoe MDL2 Assets" Content="{Binding EoIdButtonContent, Mode=TwoWay, Converter={StaticResource SegoeConverter}}" Style="{StaticResource CircleButtonStyle}" Visibility="{Binding EoVis, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding SomeProperty, Mode=TwoWay}">
<core:ChangePropertyAction></core:ChangePropertyAction>
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
So, while I can change a property using this, I don't see how to create an animation. My guess, based on my searching would be to use a Storyboard, but again, most of the solutions I've found pertain to WPF and/or don't work because the scenario is too different. If someone has a solution for this, it'd be great.
For additionaly clarity
I have button 1:
(EditButton)
When (EditButton) is clicked, I want edit button to rendertransform/animate left and the result to look like so:
(EditButton)(CancelButton)
When either edit button or cancel button are clicked, I want it to return to the original state
I am trying to create a menu (currently a ListBox containing Images) for an app (WP8 specifically, but general principal will be the same for other environments) with the behavior determined by the initial part of each gesture:
dragging/swiping the menu left or right will cause the menu to scroll left or right
dragging an item up from the menu (which is at bottom of screen) will allow it to be detached (or recreated) and placed in another container.
Roughly speaking, I understand how to drag-and-drop the element, and to make a side-scrolling menu, but I am having difficulties in putting the two together and determining whether to be in "menu scroll" mode, or "drag and drop" mode, and how to switch between the two programmatically.
<ListBox Height="100"
ItemsSource="{Binding}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
Grid.Row="1"
Name="MainMenuPicker">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding Path=Source}" Tap="Image_Tap"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Currently, horizontal scrolling is taken care of by ScrollViewer.HorizontalScrollBarVisibility="Auto"
I attempted to have a ManipluationStarted, ManipulationDelta etc to determine direction of gesture, but didn't get very far. I currently have a Tap event handler on the Image that moves moving to another parent container.
Questions:
1. How can I determine if a gesture is a side-to-side movement on the menu (ListBox) as a whole, or a drag (upwards) of an Image within the ListBox?
How can I programmatically set each case so that the functionality behaves as described?
Thanks in advance!
In this case you need to use Flick events,and use HorizaltalVelocity and vertcalvelocity to detect and distinguish between left-right and top-down swipes.
check this sample for better understanding
I am working on an application which includes a registration form. The form contains multiple text entry boxes, and so a ScrollViewer is used to allow them all to be displayed on one page.
The following is a stripped down example of the XAML code I am using:
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="SCROLLVIEWER TEST" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="registration" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<ScrollViewer Grid.Row="1">
<StackPanel>
<TextBlock Text="Hello" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello1" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello2" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello3" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello4" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello5" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello6" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello7" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="Hello8" Margin="12,0,0,0"/>
<TextBox />
<TextBlock Text="END" Margin="12,0,0,0"/>
<TextBox />
</StackPanel>
</ScrollViewer>
</Grid>
(Note that the ScrollViewer is inside a grid cell, which means that the title panel should stay OnScreen at all times)
The scrolling works perfectly fine, so that is not an issue. However, when the user selects a TextBox to enter data (i.e. the soft keyboard opens), the system pushes the content of the entire page around (including the registration title panel), which is not expected behaviour.
[See the People app on Windows Phone and try adding a new contact. This contains a similar structure, but the ScrollViewer behaves correctly by only pushing content in the scrollviewer up]
Test Cases
Select a TextBox that is visible near the top of the screen, to open the keyboard.
Attempt to scroll to the bottom of the page with keyboard open.
Items at the bottom of the page are unreachable.
or
Select a TextBox that is visible near the bottom of the screen.
Content of entire page is pushed up.
Attempt to scroll to the top of the page with keyboard open.
Items at the top of the page are unreachable, and title panel never comes back into view until keyboard is closed.
Any help on resolving this issue would be appreciated. Thanks.
The problem is that the ScrollViwer height is not modified after the keyboard appears so it becomes clipped. One solution would be to modify the height of the scrollviwer (according to the keyboard height) and then reposition it (this might give you some headaches).
Another problem is knowing when the keyboard appears - you could register for the GotFocus/LostFocus events on all your TextBoxes but it's not a great solution. This might help you: http://blogs.msdn.com/b/jaimer/archive/2010/11/05/guessing-if-the-sip-is-visible-in-a-windows-phone-application.aspx
Hope this helps a little :)
I think you can solve this by coming at the problem from another angle. The phone will scroll up the page so that the SIP (software keyboard) never covers up the TextBox which has focus.
However you can force the SIP to hide by detecting touch events on the top element contained in your ScrollViewer, e.g.:
<ScrollViewer Grid.Row="1">
<StackPanel ManipulationDelta="OnScrollViewerGridManipulationDelta">`
Then, by giving the focus to a hidden button (0x0 pixels in size) this will force the SIP to close. Then it will be possible for your users to scroll up and down the scrollviewer as expected...
private void OnScrollViewerGridManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
// This will hide the SIP if it is currently showing.
// We can't do this directly, but we can force this by taking focus away from any of the TextBoxes that may have it.
this.hiddenButton.Focus();
}
I've had the same issue with an app I've developed and the way I dealt with it was to find out the auto height of the panel containing the input textboxs and then manually set the height and add approximately 400 - 500 px to the bottom to make it scroll nicely. The effect is quite smooth and will not make your UI look "hackish" IMHO.
In your case you will have to find out the automatic height of the LayoutRoot Grid and then on RowDefinitionof Row 1 set the height manually - remembering to add an extra 400px (or whatever looks appropriate in your situation).
For ease of input I then handled each OnKeyDown event of each TextBox to change the focus to the next TextBox upon hitting Enter. On the last TextBox I set the focus to this.focus() which sets focus to the Page and hides the SIP.
Have a look at my small library please - https://siphelper.codeplex.com/
It modifies height of scrollviewer and content can be scrolled to the topmost/bottommost point.
If you have any suggestions - feel free to contact me.
I have a project where I have multiple scrollviews in one:
I can scroll up and down through a single item, and also through multiple items horizontally.
Normally, the webview is not hittestvisible.
Moving horizontally works fine, but when I scroll down, I give focus and hittestvisibility to the single item, but it won't scroll down. Only when I scroll down the second time, it will scroll, I think because when the ManipulationStartedevent was fired, it was caught by the scrollview, which had focus at the time, and only later the webview takes the focus, therefore, it has no started position. Is there a workaround for this problem?
<ScrollViewer x:Name="Scroller"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled"
ManipulationMode="Control"
Grid.Row="1" Grid.RowSpan="2" >
<StackPanel Name="WebScrollView" Orientation="Horizontal" >
<UserControl Name="LeftContentControl" MinWidth="480" />
<UserControl Name="MiddleContentControl" MinWidth="480" />
<UserControl Name="RightContentControl" MinWidth="480" />
</StackPanel>
</ScrollViewer>
So, Left, Middle and Right are the three controls which will hold the webviews as their content. When scrolled to the left( for example ), the left content is placed over the middle content, and the middle content is set into view again, so it seems like an endless list of webviews, but really are three.
I use a mediator to achieve the animation of the webviews.
Thanks in advance.
GeekPeek