UWP - How to prevent InputPane from showing and hiding automatically - c#

I want to manually control the behavior of InputPane to prevent it from showing or hiding automatically.
In my page that I put its image top, I want to InputPane show as user navigate to the page and keep showing until he/she clicks on specified button and prevent it from hiding if user clicks anywhere else in the page.
Also I want to InputPane remain hidden even if user clicks on TextBox.
I already know that there are TryShow() and TryHide(), but i can't revent auto showing and hiding.

The easy way to control it is by controlling focus of your TextBox. If you set IsTabStop on the TextBox to false - it won't take focus and so the SIP won't show up. If it already has focus - you'll need to move it out. If you want to display the SIP - focus the TextBox. Note that for performance reasons and also to prevent user confusion - it might make sense to use a TextBlock instead of a TextBox when the control should not be editable.
XAML
<Page
x:Class="App18.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App18"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<TextBox
x:Name="myTextBox"
IsTabStop="False"
AcceptsReturn="True"
VerticalAlignment="Stretch"
TextChanged="MyTextBox_OnTextChanged"/>
<Button
x:Name="myButton"
Grid.Row="1"
Click="ButtonBase_OnClick">Edit</Button>
</Grid>
</Page>
C#
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace App18
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
myTextBox.IsTabStop = true;
myTextBox.Focus(FocusState.Programmatic);
}
private void MyTextBox_OnTextChanged(object sender, TextChangedEventArgs e)
{
if (myTextBox.Text.ToLower().Contains("done"))
{
myTextBox.IsTabStop = false;
myButton.Focus(FocusState.Programmatic);
}
}
}
}

Related

Programmatically Click PrimaryButton of ContentDialog

In UWP, How can you Programmatically click the PrimaryButton of ContentDialog when KeyDown event of a textbox detects that the Enter has been pressed? Just trying to add a keyboard short cut to accept the answer In textbox and close the dialogbox all from the keyboard without needing to move the mouse and click ok.
private void A1TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
// Programmatically Click PrimaryButton Here
}
}
<ContentDialog
x:Class="App1.ContentDialog1"
Title="DialogBox"
Loaded="ContentDialog_Loaded"
PrimaryButtonText="Ok"
SecondaryButtonText="Cancel"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
SecondaryButtonClick="ContentDialog_SecondaryButtonClick">
<Grid Name="A1Grid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Name="A1TextBox" Grid.Row="0"
PlaceholderText="Search String"
TextChanged="A1TextBox_TextChanged"
KeyDown="A1TextBox_KeyDown"/>
<ScrollViewer Grid.Row="1"
ScrollViewer.VerticalScrollBarVisibility="Auto"
VerticalAlignment="Stretch">
<ListBox Name="A1ListBox" MinHeight="200"/>
</ScrollViewer>
</Grid>
</ContentDialog>
Use following Code:
RoutedEventArgs f;
private void A1TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
ContentDialog_PrimaryButtonClick (Sender, f);
}
}
than he will fire the PrimaryButtonClick Event.
Have you tried making the button you want to click the "AcceptButton"?
//This goes in the form loading method
this.AcceptButton = PrimaryButton;
This should turn the button blue, and when pressing enter on the form will result in the click function being called.project
Edit: Just noticed this isn't for winforms.
this.DefaultButton = PrimaryButton;
Thanks Bill!
The UWP ContentDialog documentation states:
"You may optionally choose to differentiate one of the three buttons as the dialog's default button. Use the DefaultButton property to differentiate one of the buttons. This button will receive the Accent Button visual treatment, respond to the ENTER key automatically, and receive focus when the Dialog is opened unless the dialog's content contains focusable elements."
Change ContentDialog as follows:
<ContentDialog … DefaultButton="Primary">

C# WPF XAML In Window Messages Boxes

I am new to C# WPF, I have created a Popup window which contains a DataGrid to hold some data. In certain cases if there are any errors in the data I want to display this error in the same popup window at the bottom of the window (See screenshot). The idea is that the user can then click ok and the message will disappear displaying the full datagrid again.
Does anybody know how to do this?
I do not want another popup message box in a separate window, I want all messages to be displayed/stacked in the same pop window as the datagrid.
Below, there are 2 grids in the XAML: There is is the master grid, which contains the DataGrid, and another grid which contains the error UI. The error grid is normally collapsed (Visibility set to Visibility.Collapsed).
When the error message needs to be shown, the error grid's Visibility is set to Visibility.Visible, which shows the grid. When the user clicks on the "Dismiss" button, the error grid's Visibility is set to Visibility.Collapsed.
There is not a separate window or popup. Everything is contained within the master view.
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DataGrid>
</DataGrid>
<Button Grid.Column="1" Content="Show Message Window" VerticalAlignment="Center" Click="Button_Click_1"/>
<!-- This is the "error grid"-->
<Grid VerticalAlignment="Bottom" Height="Auto"
Background="AliceBlue" Visibility="Collapsed" Name="grdError">
<TextBlock Text="Oops. This is an error!"/>
<Button Content="Dismiss" HorizontalAlignment="Right" Click="Button_Click_3"/>
</Grid>
</Grid>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
grdError.Visibility = Visibility.Visible;
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
grdError.Visibility = Visibility.Collapsed;
}
}

Scrollbars in a dynamically filled stack panel

I am new for WPF so apologies if the answer is so obvious.
I got a WPF resizable window with a single stack panel control that is stretched vertically and horizontally to fill the window.
On window activated event, I use ".Children.Add" to add button controls to the panel. I have no idea how many buttons will be there at runtime so I checked "CanVerticallyScroll" in the panel. ScrollViewer.VerticalScrollBarVisibility is set to Visible by default.
I am still not seeing scroll bars at runtime though.
What properties did I miss to show scrolling panel with buttons?
Thanks
XAML:
<Window x:Class="ResMed.Ecp.Utility.ConnectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="388" Width="641.6" Activated="Window_Activated">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="359*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="pnlConnectionButtons" Margin="10,10.2,10.2,10" Grid.Row="1" CanVerticallyScroll="True"/>
</Grid>
</Window>
Code behind:
private void Window_Activated(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
Button btn = new Button();
btn.Content = "Hello";
pnlConnectionButtons.Children.Add(btn);
}
}
Place your StackPanel inside a ScrollViewer:
<ScrollViewer>
<StackPanel>
<Button Content="Hello World"></Button>
...
...
</StackPanel>
</ScrollViewer>
You can also remove CanVerticallyScroll="True". From MSDN:
This property is not intended for use in your code. It is exposed publicly to fulfill an interface contract (IScrollInfo). Setting this property has no effect.

Grid column size is not recalculated properly when restoring a maximized window

I am trying to implement a kind of single-line tab control in WPF which shows scroll buttons left and right of the area containing the tabs. The tabs are implemented inside a custom control. The scroll buttons shall be displayed only if the window is too small to display all tabs.
When the window is resized by dragging on its borders, everything works as expected.
But when the window is maximimized and then restored, then the right scroll button remains hidden.
The problem seems to appear only if the Visibility property of the right scroll button is data-bound to a dependency property of the custom control that is updated within the custom control's Measure pass.
My question is: am I using WPF correctly here, or is there something that needs to be done in a different way? (Please note: I need to use the data-binding and the custom control; therefore please avoid answers that suggest to take a completely different approach.)
Here is a small sample program which illustrates the problem:
When width is small:
When width is large:
These are the files of the sample program:
MainWindow.xaml:
<Window x:Class="GridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gridTest="clr-namespace:GridTest"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="theGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnScrollLeft" Content="<" Grid.Row="0" Grid.Column="0" Width="30"/>
<gridTest:MyCustomControl x:Name="cust" Grid.Row="0" Grid.Column="1"/>
<Button x:Name="btnScrollRight" Content=">" Grid.Row="0" Grid.Column="2" Width="30"
Visibility="{Binding ElementName=cust, Path=ShowButton}"/>
<TextBox Text="The content goes here..." Grid.Row="1" Grid.ColumnSpan="3"
Background="LightGreen" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
<Button x:Name="btnRedraw" Grid.Row="1" Grid.Column="1" Content="Redraw" VerticalAlignment="Bottom"
HorizontalAlignment="Center" Click="btnRedraw_Click" />
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace GridTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnRedraw_Click(object sender, RoutedEventArgs e)
{
theGrid.InvalidateMeasure();
}
}
}
MyCustomControl.cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace GridTest
{
public class MyCustomControl : Control
{
static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
public Visibility ShowButton
{
get { return (Visibility)GetValue(ShowButtonProperty); }
set { SetValue(ShowButtonProperty, value); }
}
// Using a DependencyProperty as the backing store for ShowButton. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ShowButtonProperty =
DependencyProperty.Register("ShowButton", typeof(Visibility), typeof(MyCustomControl), new UIPropertyMetadata(Visibility.Visible));
protected override Size MeasureOverride(Size constraint)
{
if (constraint.Width > 800)
{
ShowButton = Visibility.Collapsed;
}
else
{
ShowButton = Visibility.Visible;
}
double width = Math.Min(2000.0, constraint.Width);
double height = Math.Min(50.0, constraint.Height);
return new Size(width, height);
}
}
}
Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GridTest">
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border Background="LightCyan">
<TextBlock VerticalAlignment="Center" TextAlignment="Center">Custom Control</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
The problem can be reproduced as follows:
Make sure that the window is small, such that the right scroll button is visible.
Now maximize the window. => The right scroll button should become invisible.
Now restore the window to its original size. => The right scroll button should become visible again. (The problem is: the right scroll button remains invisible.)
EDIT: Just for information: I could reproduce the problem with both VS2010+.NET4.0 and VS2013+.NET4.51.
You need to dispatch your ShowButton visibility change back into the dispatch queue for this to work(give the application the time it needs for the render and in sequence) rather than do it directly in the MeasureOverride method.
So say I change your MeasureOverride to
protected override Size MeasureOverride(Size constraint) {
if (constraint.Width > 800) {
Application.Current.Dispatcher.BeginInvoke(
new Action(() => ShowButton = Visibility.Collapsed));
} else {
Application.Current.Dispatcher.BeginInvoke(
new Action(() => ShowButton = Visibility.Visible));
}
double width = Math.Min(2000.0, constraint.Width);
double height = Math.Min(50.0, constraint.Height);
return new Size(width, height);
}
You can see it works fine.
With the original code you posted, you can see that even when you maximize your Window, the Button on the right will be hidden but not actually Collapsed like that your setting it to, that would be again due to the same reason of the control not getting it's new size.
Also after restoring and having the Button remain hidden, if you re-size the Window by dragging it's size, you can see the button become Visible again.
By dispatching the Visibility change, if you have a break-point in your MeasureOverride function, you can see it gets called twice(once for Window size change and second size change due to Button being Hidden/Shown) essentially when maximizing/restoring the Window and thereby produce the correct dimension calculations and your desired output.
Having worked with some custom Panels before, I seem to remember that the value passed into the MeasureOverride method is not the actual size used... try moving that code to the ArrangeOverride method instead and see what happens.

Why does my Page lose focus?

I have Page, and it loses focus when I tap on an empty part of it. I tried putting a Border as the background, but that loses focus too when I tap it. Why does this happen?
What I really need to do is disable a WebView when the user opens the AppBar or the Settings Charm
Some example code to demonstrate the problem (watch the output window):
XAML:
<Page
x:Name="Pagey"
x:Class="FocusTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FocusTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" GotFocus="Focus" LostFocus="LoseFocus">
<Grid x:Name="RootGrid" Background="{StaticResource ApplicationPageBackgroundThemeBrush}" GotFocus="Focus" LostFocus="LoseFocus">
<StackPanel>
<Button x:Name="Clicky" Content="Clicky" GotFocus="Focus" LostFocus="LoseFocus" HorizontalAlignment="Center"></Button>
<Border x:Name="Border" Width="100" Height="100" Background="Red" GotFocus="Focus" LostFocus="LoseFocus"></Border>
<Button x:Name="Clicky2" Content="Clicky2" GotFocus="Focus" LostFocus="LoseFocus" HorizontalAlignment="Center"></Button>
</StackPanel>
</Grid>
</Page>
Code behind:
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace FocusTest
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
void Focus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Focus({0})", (sender as FrameworkElement).Name);
}
void LoseFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("LoseFocus({0})", (sender as FrameworkElement).Name);
}
}
}
Look like your Border is inside the RootGrid So that every time when you tap Border's tap event will occur and LostFocus Event fired. Better you can set LostFocus event on the same RootGrid. Then it may work fine. Please try it.
Thanks.

Categories

Resources