I created a simple Blend behaviour to be attached to TextBox elements. It's purpose is to scroll the textbox to its end when it gets the focus, and to scroll it back to the beginning when it loses the focus.
public class TextBoxScrollToEndBehaviour : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.GotFocus += AssociatedObject_GotFocus;
AssociatedObject.LostFocus += AssociatedObject_LostFocus;
}
private void AssociatedObject_LostFocus(object sender, System.Windows.RoutedEventArgs e)
{
var textBox = sender as TextBox;
textBox.ScrollToHorizontalOffset(0);
}
private void AssociatedObject_GotFocus(object sender, System.Windows.RoutedEventArgs e)
{
var textBox = sender as TextBox;
textBox.ScrollToHorizontalOffset(double.PositiveInfinity);
}
}
Xaml:
<TextBox Text="{Binding MyBinding, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Behaviors>
<behaviours:TextBoxScrollToEndBehaviour />
</i:Interaction.Behaviors>
</TextBox>
It works great when I focus the TextBox and then I click on some other control to loose the focus. Problem is that if I switch the focus between two TextBox that share the same behaviour, the scroll is not set back to 0 on the first TextBox, even the LostFocus event is correctly triggered on it.
What am I missing here? Thanks!
.NET Framework 4.7.2
I found out that by replacing this line in the LostFocus event:
textBox.ScrollToHorizontalOffset(0);
with
textBox.ScrollToLine(0);
the behaviour works perfectly in any condition.
Related
I'm experimenting the OnPreviewMouseUp and OnPreviewMouseDown tunneling events. I'm particularly interested in e.OriginalSource as I don't understand why when I click on the text content of the button, e.OriginalSource is still the button itself, and not the text block - the visual child of the button. In fact I found the OnPreviewMouseDown event does do what I expected -- it shows e.OriginalSource as text block, however the OnPreviewMouseUp event always shows e.OriginalSource as the button itself. The following is the simple code I used for this experiment:
XAML:
<StackPanel Margin="5">
<Button Name="cmd" Margin="8">Click me.</Button>
</StackPanel>
Code behind:
public partial class ButtonMouseUpEvent : System.Windows.Window
{
public ButtonMouseUpEvent()
{
InitializeComponent();
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseDown(e);
Debug.WriteLine($"OnPreviewMouseDown(): e.Source = {e.Source}, e.OriginalSource = {e.OriginalSource}");
}
protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseUp(e);
Debug.WriteLine($"OnPreviewMouseUp(): e.Source = {e.Source}, e.OriginalSource = {e.OriginalSource}");
}
I suspect this has something to do with button's click event, which eats up the MouseUp event, but I'm trying to understand exactly why.
I'm simply trying to reset the value of a NumericUpDown element in xaml to 0 when IsEnabled becomes false, but checking for IsEnabled changes is not a routed event. This is what I currently have which doesn't work because this event is not a Routed Event
My XAML code:
<CheckBox Name="AirportTemplate">Airport</CheckBox>
<NumericUpDown Name="AirportToGen"
Width="300"
Minimum="0"
IsEnabled="{Binding ElementName=AirportTemplate, Path=IsChecked}"
IsEnabledChanged="ResetValueAirport"/>
My Code Behind C#
private void ResetValueAirport(object sender, EventArgs e)
{
if (!AirportToGen.IsEnabled)
{
AirportToGen.Value = 0;
}
}
I'm guessing you are using the NumericUpDown class form the extended WPF toolkit, in which case the IsEnabledChanged event requires a handler with the signature private void handler(object sender, DependencyPropertyChangedEventArgs e). So in your code behind use this instead:
private void ResetValueAirport(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
if (!AirportToGen.IsEnabled)
{
AirportToGen.Value = 0;
}
}
So i have the TextBox:
<TextBox Controls:TextBoxHelper.ClearTextButton="True"
LostFocus="textboxNewValueCell_LostFocus"
TextChanged="textboxNewValueCell_TextChanged"/>
And when press on Clear button i want to catch the event.
Is it possible ?
I did not find any event
The ClearTextButton simply calls Clear() on the TextBox. There is no specific event raised. The best you can do is to handle the TextChanged event:
private void textboxNewValueCell_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox tb = sender as TextBox;
if (tb.Text.Length == 0)
{
//the TextBox was cleared and the Button was maybe clicked...
}
}
First, give your TextBox a name. Then, create a click event on the Button. when the click event fires, handle the clearing of the TextBox in the CodeBehind.
<Grid>
<TextBox x:Name="MyTextBox" Text="Some Text"/>
<Button x:Name="ClearButton" Click="ClearButton_Click"/>
</Grid>
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
MyTextBox.Text = string.Empty;
}
Now the cursor is focusing in the TextBox. If i click on the the Button (RemoveLostFocus),The TextBox's Lost focus event get fired. But What i need is , Lost Focus event of TextBox should not fire. is there any way to do so ?.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
txtUserName.Focus();
}
private void UserName_LostFocus(object sender, RoutedEventArgs e)
{
if (txtUserName.Text.Length < 1)
{
MessageBox.Show("UserName should not be empty");
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
anotherWindow.Show();
}
You will want to use the FocusManager attached properties to apply the focus to the TextBox when the Button focus changes
Example:
<StackPanel>
<TextBox Name="txtbx" />
<Button Content="Click Me!" FocusManager.FocusedElement="{Binding ElementName=txtbx}"/>
</StackPanel>
With this solution the The TextBox will always be focused even when the Button is pressed and the TextBox LostFocus event will not be fired
you could Set Focusable="False" on the Button. here is a link of the answer enter link description here
Set Focusable Property
<Button Focusable="False" />
In the Click-Event of you Button you can do something like
this.textBox.Focus();
If your lostfocus-method looks like this:
private void UserName_LostFocus(object sender, RoutedEventArgs e){ ... }
you can prevent the lostfocus with the following code:
this.textBox.LostFocus -= UserName_LostFocus;
Is there anyway to add right click events to all textbox controls in silverlight without needing to manually adding it to each control in the whole project?
doing like:
<TextBox x:Name="txtName" MouseRightButtonUp="txtName_MouseRightButtonUp"
MouseRightButtonDown="txtName_MouseRightButtonDown" /></TextBox>
then fixing the events in the .cs for about 50+ (hopefully it's just 50+) textboxes can take a while.
If not then what might be the easiest way to do this?
You can extend your textbox
class SimpleTextBox
{
public SimpleTextBox()
{
DefaultStyleKey = typeof (SimpleCombo);
MouseRightButtonDown += OnMouseRightButtonDown;
}
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs
mouseButtonEventArgs)
{
//TODO something
}
}
==========
And use this control.
Or as alternative solution - you can create behavior:
CS:
...
using System.Windows.Interactivity;
public class TextBoxBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseRightButtonDown += AssociatedObject_MouseRightButtonDown;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseRightButtonDown -= AssociatedObject_MouseRightButtonDown;
}
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
e.Handled = true;
// DO SOMETHING
}
}
XAML:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<TextBox ...>
<i:Interaction.Behaviors>
<local:TextBoxBehavior />
</i:Interaction.Behaviors>
</TextBox>
And attach this handler to your TextBox general style.
My answer to this question is also the answer to your question.
In short it's probably easiest to derive a type from TextBox, put your MouseRightButtonDown event handler in there and replace all existing instances of textBox with your type.