How do I prevent the textbox from hiding the selected text highlight when the textbox loses focus? The following line worked for WPF
textBox1.IsInactiveSelectionHighlightEnabled = true;
but what is the equivalent for UWP?
You can set the SelectionHighlightColorWhenNotFocused property either in Xaml or via code. You can set it to any color you want, I just used binding to make sure it's the same color as the SelectionHighlightColor to make it easy.
<TextBox Style="{StaticResource TextBoxLightStyle}" Name="TextBoxMain"
AcceptsReturn="True"
SelectionHighlightColorWhenNotFocused="{Binding SelectionHighlightColor, ElementName=TextBoxMain, Mode=OneWay}">
</TextBox>
As I know there is no equivalent in UWP for that. One of possible work-around solutions could be to use some image to keep selection highlighted. Here is sample code:
XAML:
<Border BorderThickness="2" BorderBrush="{ThemeResource TextBoxBorderThemeBrush}" Height="164" Width="684">
<TextBox x:Name="textBox" TextWrapping="Wrap" Text="TextBox" BorderThickness="0,0,0,0"/>
</Border>
C#:
private async void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
// clear background
textBox.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 255, 255)); ;
// render image
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(textBox);
// set background
textBox.Background = new ImageBrush()
{
ImageSource = renderTargetBitmap
};
}
In focus:
Not in focus:
p.s. I'm updating background on SelectionChanged event, but actually you can create image on that event and update only on LostFocus event. It should be more efficient.
Related
How do I make the cursor in a TextBox stop blinking in WPF?
I have already tried to a MouseDown event on the parent, with one action, this.Focus();, which does not work.
You could have achieved this with HideCaret Method. However, since the WPF application cannot provide you handle for the TextBox Control (it only provides handle for Window), we cannot use HideCaret.
However, we could emulate the effect using WPF. The first step to achieve this would be disable the actual Caret. This can be done by changing the Color to transparent.
<TextBox x:Name="txtName" CaretBrush="Transparent" />
The Next step involve using a Canvas and Border to emulate the Cursor.
<Grid>
<TextBox x:Name="txtName" CaretBrush="Transparent" />
<Canvas>
<Border x:Name="Caret" Visibility="Collapsed" Canvas.Left="0" Canvas.Top="0" Width="1" Height="15" Background="Black"/>
</Canvas>
</Grid>
You need to ensure the Canvas overlap the Textbox
And in code-behind
txtName.SelectionChanged += (sender, e) => MoveCustomCaret();
txtName.LostFocus += (sender, e) => Caret.Visibility = Visibility.Collapsed;
txtName.GotFocus += (sender, e) => Caret.Visibility = Visibility.Visible;
Where MoveCustomCaret is defined as
private void MoveCustomCaret()
{
var caretLocation = txtName.GetRectFromCharacterIndex(txtName.CaretIndex).Location;
if (!double.IsInfinity(caretLocation.X))
{
Canvas.SetLeft(Caret, caretLocation.X);
}
if (!double.IsInfinity(caretLocation.Y))
{
Canvas.SetTop(Caret, caretLocation.Y);
}
}
Sample
I'm using a ComboBox with property IsEditable=true created using the following code:
ComboBox buffer = new ComboBox()
{
BorderBrush = null,
Foreground = new SolidColorBrush(Colors.Black),
Background = null,
FontFamily = new FontFamily("Segoe UI Semilight"),
FontSize = 24,
IsEditable = true,
IsTextSearchEnabled = true,
IsTextSearchCaseSensitive = false,
StaysOpenOnEdit = true,
};
It is added in a WrapPanel in a ScrollViewer defined like this :
<ScrollViewer Margin="582,107,142,240"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="226" Width="357">
<Border Background="White"
CornerRadius="10"
BorderBrush="Black"
BorderThickness="1"
MouseDown="Border_MouseDown"
MouseLeave="Border_MouseLeave"
MouseUp="Border_MouseUp">
<WrapPanel x:Name="sourcesWrapPanel" Width="357"/>
</Border>
</ScrollViewer>
It works fine when selecting manually but writing will not work (pressing the keys does not input any text). The only thing that works is selecting an item using the mouse or the up/down arrows then deleting characters in it using backspace. What am I missing?
Take a look at the documentation for ComboBox.IsEditable:
I think you need to set ComboBox.IsReadOnly to false.
The e.Handled was set to true in the parent control so only the PreviewKeyDownhandler was executed for the child (ComboBox) which is why I could only delete text or paste it but not write any.
I am dynamically adding textboxes based on a button click inside the stackpanel.But the textboxes are not visible in the UI .
Here is the code used for creating textboxs inside stackpanel.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
}
why its not visible..??and here is the XAML part of stackpanel
<StackPanel Name="panel1" Grid.Column="1" HorizontalAlignment="Left" Height="151" Margin="427,60,0,0" Grid.Row="2" VerticalAlignment="Top" Width="216">
<StackPanel Height="144">
</StackPanel>
</StackPanel>
If you are going to be adding controls dynamically, do not restrict the height (or even width) of the container you are adding to.
Update your XAML to have auto height/width.
<StackPanel Name="panel1"
Grid.Column="1"
Height="Auto"
Width="Auto"
Margin="427,60,0,0"
Grid.Row="2"
VerticalAlignment="Top"
HorizontalAlignment="Left" >
<StackPanel Height="144">
</StackPanel>
</StackPanel>
Also, once you add a new child, make sure you are updating the StackPanel layout.
public void GenerateControls()
{
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
txtNumber.Background= Brushes.Red;
panel1.Children.Add(txtNumber);
panel1.UpdateLayout();
}
In your xaml code, there is a stackpanel in your 'panel', it will be the 1st child of 'panel'.
And its height is 144px. your 'panel1' is 151 px.
So when you add textboxes into 'panel', they will be displayed behind the 144px stackpanel.
There is only 7px to display them. So they will not display on your window.
I'm using a list of textboxes for a registering document in a WP8 app.
The number of textboxes is quite large, so the user has to scroll between them.
To navigate between one field to another, I added two applicationbarIcons, next and previous. Pressing on next will change the focus to the next textbox from list, and scroll the content of the scroll viewer with the height of the textbox (in this case 50).
However, sometimes, when switching the focus to the element bellow, the keyboard covers the text box. (the content doesn't scroll up).
Is there a way to force the textbox to move above the keyboard, even if it is in a scroll view?
<ScrollViewer x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock Text="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.STRING_CONTACT}" Margin="10,5" FontWeight="SemiBold" Foreground="#878780"></TextBlock>
<StackPanel Margin="10,5" Height="190" Background="#F4F3F4">
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="firstNameTxt" BorderThickness="0" Background="Transparent" InputScope="PersonalFullName"><TextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="lastNameTxt" BorderThickness="0" Background="Transparent" InputScope="PersonalFullName"></my:DefaultTextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="MobileTxt" BorderThickness="0" InputScope="Number" Background="Transparent" ></TextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="EmailTxt" BorderThickness="0" Background="Transparent">
</StackPanel>
</ScrollViewer>
Code behind:
void left_Click(object sender, EventArgs e)
{
int index = this.controls.IndexOf(currentControl) - 1;
if (index == -1)
{
this.Focus();
return;
}
currentControl = this.controls[index];
ContentPanel.ScrollToVerticalOffset(ContentPanel.VerticalOffset - 50);
currentControl.Focus();
}
This is a common issue on WP8. When a textbox is focused, it will translate Application 's RootVisual to bring it into view. This doesn't work well in some cases (when clipboard is on, or in your case). A workaround is manually translating RootVisual to a desired vertical offset on GotFocus and LostFocus events of TextBox.
private void TranslateRootVisualY(int yNew)
{
var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
rootFrame.RenderTransform = new CompositeTransform() {TranslateY = yNew};
}
In your case, you can eliminate the automatic translation and make ScrollViewer scroll to desired offset in GotFocus event:
private void firstNameTxt_GotFocus_1(object sender, RoutedEventArgs e)
{
TranslateRootVisualY(0);
Dispatcher.BeginInvoke(() =>{
double destOffset;
//...calculate destination offset
ContentPanel.ScrollToVerticalOffset(destOffset);
});
}
destOffset can be calculated from sender and other function like GetRectFromCharacterIndex
I am new to both C# and XAML and I am making some sort of reading application.
So I need a TextBlock that word wraps if the title needs more than 1 row to fit. But when it becomes more that 2 rows to fit, wrap a ScrollView on it.
By doing this I could align the rest element tightly whenever it is either 1 or 2(max) row height.
How do I achieve this in XAML or C#?
If you can use a TextBox instead of a TextBlock, it would be easier. A TextBox supports scrolling and has a LineCount property that you can key off of. So for example, I put the a few controls into a StackPanel:
<Grid>
<StackPanel HorizontalAlignment="Left" Height="100" Margin="105,127,0,0" VerticalAlignment="Top" Width="184">
<TextBox Height="23" TextWrapping="Wrap" Text="TextBox" Name="TextBox1"/>
<Button Content="Button" Click="Button_Click_2"/>
</StackPanel>
</Grid>
Then I had some code to update the text. When I hit 2 lines, I grew the TextBox and when I got to three lines, I added scrollbars:
private void Button_Click_2(object sender, RoutedEventArgs e)
{
TextBox1.Text += "More Text";
if (TextBox1.LineCount >= 2)
{
TextBox1.Height = 38;
}
if (TextBox1.LineCount >= 3)
{
TextBox1.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
}
}