How to avoid ListView item losing focus? - xaml

I have a UserControl that controls scrolling of a ListView, kind of like a custom ScrollBar. The issue occurs when:
An item in the ListView has keyboard focus (i.e. the focus visual is
set on the item)
I grab and drag my control
Make the release outside of the control (e.g. over the ListView)
Result is that the ListView item loses its focus in the same way it would if I had just clicked outside of the ListView. This is not the way a regular ScrollBar behaves and in fact if I have a Button in my control, click that and make the release outside of the control the Button somehow blocks the release event and the ListView item keeps its focus.
I've tried setting CapturePointer in the PointerPressed handler of my UserControl, but the item still loses focus (although the PointerReleased handler of the ListView isn't called).
UserControl:
<Grid x:Name="RootGrid" Background="AliceBlue">
<Button IsTabStop="False">OKOK</Button>
</Grid>
MainPage:
<Grid x:Name="RootGrid" Background="Gray">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ListView>
<TextBlock Text="ListViewItem 1" />
<TextBlock Text="ListViewItem 2" />
<TextBlock Text="ListViewItem 3" />
</ListView>
<local:MyControl Grid.Row="1" />
</Grid>
So in the above example:
Press tab so that an item in the ListView is marked with the black focus rectangle
Press the blue area with the mouse, drag to gray area and release
Notice how the black focus rectangle disappears. Repeat the steps above but press the Button instead of pressing the blue area and notice how the black focus rectangle doesn't disappear. I want the same behavior when dragging from the blue area as when dragging from the Button.

Related

How can you keep focus when pressing a disabled button in a scrolviewer in xaml?

When creating a default C++ xaml blank app for UWP from visual studio add the following code in the xaml page.
<ScrollViewer>
<StackPanel>
<TextBox Height="20"></TextBox>
<TextBox Height="800"></TextBox>
<Button Content="Enabled" IsEnabled="True"></Button>
<Button Content="Disabled" IsEnabled="False"></Button>
</StackPanel>
</ScrollViewer>
If I put the focus on the Enabled button and after that I press the disabled button the focus shifts to the first TextBox.
I found a workaround, to add a 0 dimension focusable element as the first element of the stack panel. <Button Width="0" Height="0"></Button>
But this will affect the other children. ( The id will be changed by 1 )
Do you know a more elegant way of keeping the focus on the previous element after pressing a disabled button in a panel from a scollviewer?
The behavior is not present if the stackpanel is not in a scrollviewer.
You can programmatically change the app's focus in the ScrollViewer's Tapped event.
In the xaml:
<ScrollViewer Tapped="ScrollViewer_Tapped">
<StackPanel>
<TextBox Height="20"></TextBox>
<TextBox Height="200"></TextBox>
<Button Content="Enabled" x:Name="EnableButton"></Button>
<Button Content="Disabled" IsEnabled="False"></Button>
</StackPanel>
</ScrollViewer>
In the xaml.cpp, handle the ScrollViewer_Tapped event to make the EnableButton get focus.
void CApp::MainPage::ScrollViewer_Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
{
EnableButton->Focus(Windows::UI::Xaml::FocusState::Programmatic);
}
If you have any other Controls who can get focus, you should also handle their similar event to assign the focus.
Found a solution. On PointerPressed get the current focused element as an UIElement^ and capture the pointer

XAML: MouseLeftButtonUp only fires when clicking text, not whitespace

I have a list box (in Silverlight) that uses a DataTemplate for the ItemTemplate. The DataTemplate is defined like this:
<DataTemplate>
<StackPanel Orientation="Horizontal"
MouseLeftButtonUp="RoleStackPanel_MouseLeftButtonUp"
Tag="{Binding}">
<TextBlock Name="roleItem"
Text="{Binding Path=DisplayValue, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
I have found that my event RoleStackPanel_MouseLeftButtonUp only fires if any text displayed in the TextBlock is clicked. If the user clicks any whitespace in the item to the right of the text, the event does not fire. So lets say the control is 300px wide but only has the word "Admin" in the item, you MUST click "Admin" and not to the empty whitespace to the right.
How can I make it so the events fires wherever I click in the item, on text or whitespace?
So a couple quick considerations to get you sorted.
a.) The area of your panel does not have HitTestVisibility by default. This is by design and intentional. To get your event to fire for the parent simply add the property of IsHitTestVisible="True" or provide a Brush for the panel via Background="Transparent" to it to invoke HitTestVisibility.
b.) A StackPanel will only consume the space required by its children. If you wish to provide a large area for a user to hit like you describe than swap the StackPanel for Grid which should consume whatever space is made available by its parent. Same rules of HitTestVisibility apply.
<DataTemplate>
<Grid IsHitTestVisible="True"
MouseLeftButtonUp="RoleStackPanel_MouseLeftButtonUp"
Tag="{Binding}">
<TextBlock Name="roleItem"
Text="{Binding Path=DisplayValue, Mode=TwoWay}" />
</Grid>
</DataTemplate>
Hope this helps, cheers!

How to fix the ScrollViewer/ListBox height to be the screen height?

I have a Universal Windows Platform application.
I have a ScrollViewer which has a button on the top, a ListBox and a button below the ListBox (I know it is not a good practice to have a ListBox inside a ScrollViewer, but this is not my code and I can't modify the implementation).
The ScrollViewer's VerticalScrollMode and VerticalScrollBarVisibility are both set to false, so it is not possible to scroll vertically (this is also a requirement).
When the ListBox contains many items, the height of the list becomes bigger than the device height. As a result a part of the ListBox and the Buttons below the list are not available (as the vertical scroll is disabled).
<ScrollViewer>
<RelativeLayout>
...
<Button name="Button1">
...
</Button>
<ListBox MinHeight="120">
</ListBox>
<Button name="Button2">
...
</Button>
</RelativeLayout>
</ScrollViewer>
Is there a way to fix the ScrollViewer's height to be the device screen height? And fix the ListBox's height so that the ListBox's height grows only so that the ListBox fits on the space between the Button1 and Button2?
Your problem is not the scrollviewer's height. It is the listbox that expands to accomodate it's contents (as it should). By limiting the listbox's height you can take care of that.
You can use a grid with 3 rows. Something like this
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="ButtonTop" Grid.Row=0/>
<ListView x:Name="DontPutListViewInScrollViewer" Grid.Row=1/>
<Button x:Name="ButtonBottom" Grid.Row=2/>
</Grid>
Notice the Height defined in the middle row. That means that the listview will take all space that the top and bottom row leave available.
Then put this grid in the ScrollViewer.

Windows Phone items scroll issue while SIP keyboard appear

I'm facing two issues with the code following while I'm making a simple chat app.
The code shows a textblock at the top of the page and two textbox stack at the bottom. Plus a listbox which will be auto height to fill the remaining gap.
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle Height="1" Fill="White" VerticalAlignment="Top"/>
<TextBlock Text="Hello World!" Grid.Row="0" FontSize="36"/>
<Listbox Grid.Row="1"/>
<TextBox Grid.Row="2"/>
<TextBox Grid.Row="3"/>
</Grid>
When I click on one of the top textboxes, the SIP keyboard becomes visible and all content in the page is pushed up. The main issue here is that the top textblock disappears and hides over the top. How can I keep it on top and not moving while the SIP keyboard is viewed?
When the most bottom textbox has focus, the SIP keyboard appears and pushes all content up. In this case, the keyboard will just fit and be sticky to that textbox. However, when the other textbox has focus, the keyboard will make a gap between them. How can I make the keyboard behave as it does when the most bottom one is focused?
When the keyboard pops and unpops, a TranslateTransform runs on the PhoneApplicationFrame, translating the whole screen up and down.
Based on this article, you should be able to get the value of the translation. As you can observe an animation moves the Y property from zero to a specific negative value (based on the control you took focus on).
Option 1: I have not been able to write a descent way of handling this value but you should be able to resize your controls to fit in what's left of the screen.
Option 2.0 (bad): You can cancel or remove this animation. The keyboard will be on top of the screen without any movement. Your turn now to move/resize your controls to fit the remaining space.
public MainPage()
{
this.InitializeComponent();
PhoneApplicationFrame frame = (App.Current as App).RootFrame;
var group = (frame.RenderTransform as TransformGroup);
group.Children.RemoveAt(0); // remove translate transform
}
Option 2.1: There's an issue with 2.0: removing the transform will prevent you from being notified about the keyboard. Setting up a reverse animation on your page's child when the Y property changes will "kind of cancel" the original translation.
<Grid x:Name="LayoutRoot" Background="Transparent" VerticalAlignment="Stretch">
<Grid.RenderTransform>
<TransformGroup>
<TranslateTransform />
</TransformGroup>
</Grid.RenderTransform>
static void OnRootFrameTransformChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
// ... edit from the blog article ...
MainPage page = source as MainPage;
page.lb.Items.Add(newvalue);
var oppositeTransform = (TranslateTransform)((TransformGroup)page.RenderTransform).Children[0];
if (newvalue < 0.0)
{
page.IsSipVisibleGuess.IsChecked = true;
oppositeTransform.Y = -newvalue;
}
else if (newvalue == 0.0)
{
page.IsSipVisibleGuess.IsChecked = false;
oppositeTransform.Y = 0;
}
I'm sorry none of these options will magically solve the problem but it may help you code what fits best for your app.
If you find a better solution out of this, please post it as an answer.

Setting Panorama Background for user control in Panorama page

How set the Panorama page Background for User control which is inside the PanoramaItem ?
I had put one user control in Panorama Item. I expect that the same panoroma background is applied to user control, but its not, there is a difference..? how to set the normal Panorama Back ground to the user control which is bound to the panorama item.
<controls:Panorama Grid.Row="1">
<!--Panorama item one-->
<controls:PanoramaItem Header="{Binding Path= Localizedresources.RecentPanoramaItemHeader, Source={StaticResource LocalizedResources}}">
<views:RecentFileView DataContext="{Binding RecentFileViewModel}" />
</controls:PanoramaItem>
<!--Panorama item two-->
<controls:PanoramaItem Header="{Binding Path= Localizedresources.FileserversPanoramaItemHeader, Source={StaticResource LocalizedResources}}">
<views:DashboardView DataContext="{Binding DashboardViewModel}" />
</controls:PanoramaItem>
<!--Panorama item three-->
<controls:PanoramaItem Header="{Binding Path= Localizedresources.MenuPanoramaItemHeader, Source={StaticResource LocalizedResources}}">
<Grid>
</Grid>
</controls:PanoramaItem>
<!--Panorama item four-->
<controls:PanoramaItem Header="{Binding Path= Localizedresources.TheftguardPanoramaItemHeader, Source={StaticResource LocalizedResources}}">
<Grid/>
</controls:PanoramaItem>
</controls:Panorama>
While I am running the application I can see the difference in Back ground of user control. I need the same feel as Panorama not the user control. for that I need the back ground of user control is same as Panorama. - while applying light theam to phone.
I need a transparent background of user control.
I suspect that one (or more) of your UserControls has a Background value set on the root element. The default UserControl that gets added in Visual Studio has the Background property on the root Grid (named LayoutRoot) set: Background="{StaticResource PhoneChromeBrush}", which is not transparent. If you simply remove the Background property, the UserControl will become transparent: <Grid x:Name="LayoutRoot">.