WPF EditingCommands is not working when RichTextBox is just load/empty? - c#

Here is a very simple code example:
<DockPanel>
<ToolBar DockPanel.Dock="Top" IsTabStop="False">
<ToggleButton MinWidth="40" Command="EditingCommands.ToggleBold" CommandTarget="{Binding ElementName=XAMLRichBox}" TextBlock.FontWeight="Bold" IsTabStop="False">B</ToggleButton>
</ToolBar>
<RichTextBox x:Name="XAMLRichBox" SpellCheck.IsEnabled="True" MinHeight="100"/>
</DockPanel>
when I run it, after typing something into the RichTextBox, I can use the ToggleButton to get the BOLD effect, and everything is fine.
But if I click ToggleButton before typing in anything into RichTextBox (no matter RichTextBox get focus or not), although ToggleButton became Checked, my RichTextBox still using the normal style (not BOLD) until I click ToggleButton again.
Is this a bug? how can I get around? Thanks!

Mainwindow.xaml
<DockPanel>
<ToolBar
DockPanel.Dock="Top"
IsTabStop="False">
<ToggleButton
x:Name="boldButton"
Command="EditingCommands.ToggleBold"
CommandTarget="{Binding ElementName=XAMLRichBox}"
TextBlock.FontWeight="Bold"
ToolTip="Bold">
B
</ToggleButton>
</ToolBar>
<RichTextBox
x:Name="XAMLRichBox"
SpellCheck.IsEnabled="True"
SelectionChanged="SynchronizeWith"
MinHeight="100" />
</DockPanel>
Mainwindow.xaml.cs
private void SynchronizeWith(object sender, RoutedEventArgs e)
{
object currentValue = XAMLRichBox.Selection.GetPropertyValue(TextElement.FontWeightProperty);
boldButton.IsChecked = (currentValue == DependencyProperty.UnsetValue) ? false : currentValue != null && currentValue.Equals(FontWeights.Bold);
}

I found a semi-solution and I thought I would share since this problem is not answered anywhere on the web and I think many people are having issues with it.
I set a Variable NewInput in the constructor. When the first input in the richTextBox will be fired, I'll just apply every formating I need to it and pass it to the control.
private bool NewInput;
private void richTxt_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (NewInput)
{
richTxt.BeginChange();
TextPointer startPosition = richTxt.Selection.Start;
Run r = new Run(e.Text, startPosition);
if (IsSelectionBold)
{
r.FontWeight = FontWeights.Bold;
}
if (IsSelectionItalic)
{
r.FontStyle = FontStyles.Italic;
}
if (IsSelectionUnderlined)
{
r.TextDecorations = TextDecorations.Underline;
}
r.FontSize = double.Parse(SelectedFontHeight);
r.FontFamily = new FontFamily(SelectedFont);
richTxt.EndChange();
NewInput = false;
e.Handled = true;
richTxt.CaretPosition = richTxt.CaretPosition.GetPositionAtOffset(1);
}
}
I then replace the carret at the right place. Like this, the formating is kept even if there is nothing in the RichTextBox.
I'm sure it'll help somebody one day.

#Sinity was close, but that solution does not work when the caret is placed within the text block, only if it is at the very end.
There are two positions at the end of a Run: Run.ContentEnd and Run.ElementEnd. It appears that the ContentEnd is "just outside" the run (so any new text entered does not take on the run's style), but ElementEnd is "just inside" the end of the run, and the typed text is added into the run.
Here is a modified solution (that applies a pending Bold style as an example) that seems to work in all cases:
private bool IsBoldStylePending { get; set; }
private void RichTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!IsBoldStylePending)
return;
rtb.BeginChange();
Run run = new Run(e.Text, rtb.CaretPosition); // Add the next character with style
run.FontWeight = FontWeights.Bold;
rtb.EndChange();
rtb.CaretPosition = run.ElementEnd; // Keep caret just within the run
IsBoldStylePending = false;
e.Handled = true;
}

Related

Set TextBox AccessText without an accompanying Label

I have a series of textboxes in a usercontrol that do not have accompanying Labels.
I need to provide a means for a user to press Alt+(Some Key) to set focus to each of these textboxes.
If I want to use the built in WPF "AccessText" way of doing this, I would need to put a Label up next to each textbox, specify the content with an '_' character preceding the shortcut key, and specify the "Target" property of each Label to their respective Textbox.
Unfortunately in this case, there are no Labels for each textbox, and there will not be.
Is it possible to specify the AccessText shortcut key for a textbox, without a Label?
you can Handle key combinations press and after that focus on the TextBox :
*.xaml:
<UserControl Loaded="UserControl_Loaded">
<Grid>
<StackPanel>
<TextBox Height="30" x:Name="txt1"/>
<TextBox Height="30" x:Name="txt2"/>
</StackPanel>
</Grid>
</UserControl>
*.cs
public UserControl()
{
InitializeComponent();
}
private void KeyDownEvent(object sender, KeyEventArgs e)
{
bool x = Keyboard.IsKeyDown(Key.System);
if (Keyboard.IsKeyDown(Key.System) && Keyboard.IsKeyDown(Key.B))// Alt+B
{
txt2.Focusable = true;
txt2.Focus();
}
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
var window = Window.GetWindow(this);
window.KeyDown += KeyDownEvent;
txt1.Focusable = true;
txt1.Focus();
}
}

How to use Tag for compare value from database

i want to learn c#.net ., please help me to fix the code ,The quetion is => ., how to use property Tag for compare a value from database???
i use microsoft visual studio 2010
this project goal to make a Matching game picture
this is code from UI
<StackPanel Height="117" HorizontalAlignment="Left" Margin="6,23,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="136" Tap="stackpanel_Tap_1">
<Image Source="{Binding SOAL }" Name="Gambar1" Tag="{Binding ID_GAME}" />
</StackPanel>
this is from class
This class i want to make prosedure(void) event click, in this void if i click a stackpanel i will get a ID_GAME, and then i click another stackpanel to compare the ID_GAME, if ID_GAME is match, it will be continue the game.
private void stackpanel_Tap_1(object sender, GestureEventArgs e)
{
StackPanel firstklk = null;
StackPanel scndklk = null;
StackPanel Stn = (StackPanel)sender;
if (Stn != null)
{
if (firstklk == null)
{
Stn.Tag = this.Tag;
firstklk.Tag = Stn.Tag;
return;
}
scndklk.Tag= Stn.Tag;
if (firstklk.DataContext == scndklk.DataContext)
{
MessageBox.Show("MATCH");
}
}
else
{
MessageBox.Show(" Not Match ");
}
}
if you have another way, you can tell me the code? thanks for help me
AS #KillQuotes wrote you need to implement MVVM pattern here. If you are new in the environment is a good advice to read this document carefully, then you can build your application. Just for reference, you can watch this video. ;)

How to detect if the scroll viewer reaches bottom in winrt

I'm wondering what's the best approach to detect if a ScrollViewer reaches the bottom, right etc.
I think I can achieve that by using both PointerWheelChanged for mouse and ManipulationDelta for touch. In these event handlers, I can record the HorizontalOffset to find out when will the scroller reach the end. But I think there could be a better way to do it.
I've found this article. But the compression visual states seem not working in winrt. The CurrentStateChanging event method is not getting called.
I also checked another article. But it just works for scroll bar, not a generic approach.
Anyone knows what's the best way to solve this problem?
XAML:
<ScrollViewer
x:Name="sv"
ViewChanged="OnScrollViewerViewChanged">
<Rectangle
x:Name="rect"
Width="2000"
Height="2000"
Fill="Yellow"
Margin="10" />
</ScrollViewer>
Code behind:
private void OnScrollViewerViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var verticalOffset = sv.VerticalOffset;
var maxVerticalOffset = sv.ScrollableHeight; //sv.ExtentHeight - sv.ViewportHeight;
if (maxVerticalOffset < 0 ||
verticalOffset == maxVerticalOffset)
{
// Scrolled to bottom
rect.Fill = new SolidColorBrush(Colors.Red);
}
else
{
// Not scrolled to bottom
rect.Fill = new SolidColorBrush(Colors.Yellow);
}
}
For UWP I got it like this
<ScrollViewer Name="scroll" ViewChanged="scroll_ViewChanged">
<ListView />
</ScrollViewer>
private void scroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var scrollViewer = (ScrollViewer)sender;
if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
btnNewUpdates.Visibility = Visibility.Visible;
}
private void btnNewUpdates_Click(object sender, RoutedEventArgs e)
{
itemGridView.ScrollIntoView(itemGridView.Items[0]);
btnNewUpdates.Visibility = Visibility.Collapsed;
}

What is the correct way to code the nested methods?

I have created a registration form in silverlight 4, where i have a large number of text-boxes, in front of each text box i have placed a text-block as a required field validator, when any of the textbox left empty while loosing focus, the textblock placed in front of it must become red.
textboxes named textbox1, textbox2 ... and so as the textblocks
the problem is, i do not want code the specific method for each specific textbox, all i want to do is to complete such in just two three methods
here i did some coding which doesn't seems to be correct
private void textBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = (TextBox) sender;
if (textbox.Text == "")
{
var textblock = "textblock" + textBox.Name.Remove(0,7);
TextblockColorChange(textblock);
}
}
private void TextblockColorChange(object sender)
{
var textblock = (TextBlock) sender;
textblock.Foreground= new SolidColorBrush(Colors.Red);
}
please suggest some better way to do so..
I'd create a UserControl that contains the TextBlock and the TextBox and use this UserControl everywhere you currently have the TextBlock and TextBox combination. Then this Usercontrol would have the LostFocus logic inside it and update the TextBlock appropriately. This prevents the need to figure out the right name of the control to update.
you need something like this,
XAML part:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal" Height="25">
<TextBox Width="150" LostFocus="TextBox_LostFocus"/>
<TextBlock Text="*" Foreground="#FF0000" VerticalAlignment="Center" Margin="10,0,0,0" Visibility="Collapsed"/>
</StackPanel>
</Grid>
C# Part:
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textbox = sender as TextBox;
if(textbox == null) return;
var stackPanel = textbox.Parent as StackPanel;
if(stackPanel == null) return;
var textBlock = stackPanel.Children.Where(a => a is TextBlock).FirstOrDefault();
if (textBlock == null) return;
if (string.IsNullOrEmpty(textbox.Text)) textBlock.Visibility = Visibility.Visible;
else textBlock.Visibility = Visibility.Collapsed;
}
Whilst I actually prefer Bills approach (although I'd be inclined to use a Templated Control) here is another alternative which is quite fun. In your xaml use this sort of markup:-
<TextBlock Text="Enter Value 1" Foreground="{Binding Tag, ElementName=textBox1, TargetNullValue=Black}" />
<TextBox x:Name="textBox1" LostFocus="txt_LostFocus" />
Your common txt_LostFocus can look like this:-
private void txt_LostFocus(object sender, RoutedEventArgs e)
{
TextBox txt = ((TextBox)sender);
if (String.IsNullOrEmpty(txt.Text))
{
txt.Tag = new SolidColorBrush(Colors.Red);
}
else
{
txt.Tag = null;
}
}
var textblock = "textblock" + textBox.Name.Remove(0,7);
TextblockColorChange(textblock);
This code above will just send a string to TextblockColorChange()
You don't show any other code, but I'm guessing you want to do a FindControl or FindControl like search on that string before passing the result to your code.

Allow only numeric entry in WPF Text Box

I will like to validate user entry to ensure they are integers. How can I do it? I thought of using IDataErrorInfo which seems like the "correct" way to do validation in WPF. So I tried implementing it, in my ViewModel.
But the thing is my text box is bound to an integer field, and there isn't any need to validate if an int is an int. I noticed that WPF automatically adds a red border around the textbox to notify the user of the error. The underlying property doesn't change to an invalid value. But I would like to notify the user of this. How can I do it?
Another way is simply to not allow values that are not integers.
The following implementation is a little bit sucky, and I would like to abstract it later on in order for it to be more reusable, but here is what I did:
in the code behind in my view (I know this is might hurt if you are a hardcore mvvm ;o) )
I defined the following functions :
private void NumericOnly(System.Object sender, System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = IsTextNumeric(e.Text);
}
private static bool IsTextNumeric(string str)
{
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[^0-9]");
return reg.IsMatch(str);
}
And in the XAML view, every textbox that was only supposed to accept integers
was defined like this:
<TextBox Padding="2" TextAlignment="Right" PreviewTextInput="NumericOnly" Text="{Binding xxx.yyyy}" MaxLength="1" />
The key attribute being PreviewTextInput
The red border you've seen is actually a ValidationTemplate, which you can extend and add a info for the user. See this example:
<UserControl.Resources>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Label Foreground="Red" HorizontalAlignment="Right" VerticalAlignment="Center">Please insert a integer</Label>
<Border BorderThickness="1" BorderBrush="Red">
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<TextBox Name="tbValue" Validation.ErrorTemplate="{StaticResource validationTemplate}">
We can do validation on text box changed event.
The following implementation prevents keypress input other than numeric and one decimal point.
private void textBoxNumeric_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
Int32 selectionStart = textBox.SelectionStart;
Int32 selectionLength = textBox.SelectionLength;
String newText = String.Empty;
int count = 0;
foreach (Char c in textBox.Text.ToCharArray())
{
if (Char.IsDigit(c) || Char.IsControl(c) || (c == '.' && count == 0))
{
newText += c;
if (c == '.')
count += 1;
}
}
textBox.Text = newText;
textBox.SelectionStart = selectionStart <= textBox.Text.Length ? selectionStart : textBox.Text.Length;
}
if you are working in WPF Better to use PreviewTextInput event which support all platforms and from presentationcore.dll
here is the example:
private void TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
if ((e.Text) == null || !(e.Text).All(char.IsDigit))
{
e.Handled = true;
}
}
Here is how to create a numeric field in WPF, using the regular expressions.
XAML:
<TextBox PreviewTextInput="NumberValidationTextBox"></TextBox>
Code behind:
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}

Categories

Resources