WPF event trigger for clear TextBox - wpf

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;
}

Related

Problem with same Blend behaviour applied to multiple elements

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.

How to avoid lost focus of TextBox when click a button in wpf?

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;

Button on ListBox Item

I have a ListBox filled with items. Some of the items may have buttons or links within RichTextBlock inside. I want to fire different action either when the item is pressed or when the button is pressed. The problem is when I hit the button, also the action connected with the item itself is fired. How can I prevent fireing the event of list item when the button inside is pressed?
ListBox:
<ListBox x:Name="StripesList" SelectionChanged="StripesList_SelectionChanged">
</ListBox>
ListBox Items:
<Border x:Name="OuterBorder" Width="400">
<Image x:Name="ThumbnailBox" Width="100" Source="{Binding Thumbnail}" Tap="ThumbnailClick" />
</Border>
Code:
private void StripesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (StripesList != null)
{
StripesList.SelectedIndex = -1;
}
}
private void ThumbnailClick(object sender, System.Windows.Input.GestureEventArgs e)
{
Image image = sender as Image;
// handle image click
}
private void ItemClick(object sender, EventArgs e)
{
// handle item click
}
I register item click event observers from code behind:
item.Tap += new EventHandler(ItemClick);
set e.Handled=true in the handler of all events . It will stop the Bubbleing of the event.

Is there any way to prevent a WPF CheckBox from firing its Checked event?

I have a group of WPF CheckBoxes that have a Checked event handler that handles some logic when the user clicks on one of them. However, I also have a "Clear All" button that, when clicked, will clear all the checkboxes. If the user clicks on the "Clear All" button, I do NOT want the checkboxes to fire their Checked event. Is there a way of doing this?
You may use the 'Click' event instead of 'Checked' or 'Unchecked' events.
'Click' will ensure that the state change will come from the user input (via mouse button or space bar for instance).
And operations like cb.IsChecked = value wont fire the 'Click' event.
Remove the event handler at the beginning of the in the Clear All button's event handler and then re-add the event handler at the end of the Clear All button's event handler.
Here's a dirty sample:
XAML
<Window x:Class="UncheckedTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<CheckBox Height="16" Margin="22,30,136,0" Name="checkBox1" VerticalAlignment="Top"
Unchecked="checkBox1_Unchecked">CheckBox 1</CheckBox>
<CheckBox Height="16" Margin="22,76,136,0" Name="checkBox2" VerticalAlignment="Top"
Unchecked="checkBox2_Unchecked">CheckBox 2</CheckBox>
<CheckBox Margin="22,0,136,121" Name="checkBox3" Height="16" VerticalAlignment="Bottom"
Unchecked="checkBox3_Unchecked">CheckBox 3</CheckBox>
<Button HorizontalAlignment="Right" Margin="0,118,37,121" Name="button1" Width="87"
Click="button1_Click">Uncheck All</Button>
<TextBox Height="74" Margin="22,0,20,13" Name="textBox1" VerticalAlignment="Bottom"
TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" />
</Grid>
</Window>
Code Behind
using System;
using System.Windows;
namespace UncheckedTest
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private int i = 1;
public Window1()
{
InitializeComponent();
}
void checkBox3_Unchecked(object sender, RoutedEventArgs e)
{
textBox1.Text = i++.ToString() + ". Checkbox 3 Unchecked." + Environment.NewLine + textBox1.Text;
}
void checkBox2_Unchecked(object sender, RoutedEventArgs e)
{
textBox1.Text = i++.ToString() + ". Checkbox 2 Unchecked." + Environment.NewLine + textBox1.Text;
}
void checkBox1_Unchecked(object sender, RoutedEventArgs e)
{
textBox1.Text = i++.ToString() + ". Checkbox 1 Unchecked." + Environment.NewLine + textBox1.Text;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
checkBox1.Unchecked -= checkBox1_Unchecked;
checkBox2.Unchecked -= checkBox2_Unchecked;
checkBox3.Unchecked -= checkBox3_Unchecked;
checkBox1.IsChecked = false;
checkBox2.IsChecked = false;
checkBox3.IsChecked = false;
checkBox1.Unchecked += checkBox1_Unchecked;
checkBox2.Unchecked += checkBox2_Unchecked;
checkBox3.Unchecked += checkBox3_Unchecked;
}
}
}
It would be ideal to disable the event but I don't know how that would be done.
Though it would be just as easy to add a boolean to keep track if whether or not the "Clear All" button was pressed. Then only do the Unchecked code if it wasn't unchecked through the button.
private bool clearAllClicked = false;
private void button_Click(object sender, RoutedEventArgs e)
{
clearAllClicked = true;
checkbox.IsChecked = false;
clearAllClicked = false;
}
private void checkbox_Unchecked(object sender, RoutedEventArgs e)
{
if (!clearAllClicked)
{
//do stuff
}
}

How do I stop binding properties from updating?

I have a dialog that pops up over the main screen (it's actually a user control that appears on the page as per the application demo from Billy Hollis) in my application that has data from the main screen to be edited. The main screen is read only.
The problem I have is that when I change the data in the dialog, the data on the main screen updates as well. Clearly they are bound to the same object, but is there a way to stop the binding update until I click save in my dialog?
You could use a BindingGroup :
...
<StackPanel Name="panel">
<StackPanel.BindingGroup>
<BindingGroup Name="bindingGroup"/>
</StackPanel.BindingGroup>
<TextBox Text="{Binding Foo}"/>
<TextBox Text="{Binding Bar}"/>
<Button Name="btnSubmit" Content="Submit" OnClick="btnSubmit_Click"/>
<Button Name="btnCancel" Content="Cancel" OnClick="btnCancel_Click"/>
</StackPanel>
...
Code behind :
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
panel.BindingGroup.BeginEdit();
}
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
panel.BindingGroup.CommitEdit();
panel.BindingGroup.BeginEdit();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
panel.BindingGroup.CancelEdit();
panel.BindingGroup.BeginEdit();
}
Have a look at the Binding.UpdateSourceTrigger property.
You can set the Binding in your dialog like so
<TextBox Name="myTextBox"
Text={Binding Path=MyProperty, UpdateSourceTrigger=Explicit} />
And then call the UpdateSource method in your button save event
myTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
Once you've called UpdateSource the source object will be updated with the value from the TextBox
I also choose to use BindingGroup. But instead of BeginEdit() / CommitEdit() / CancelEdit() pattern I call UpdateSource() explicitly on all the bindings associated with BindingGroup. This approach allows me to add only one event handler instead of 3.
private void OkButton_Click(object sender, RoutedEventArgs e)
{
CommitChanges();
DialogResult = true;
Close();
}
private void CommitChanges()
{
foreach (var bindingExpression in this.BindingGroup.BindingExpressions)
{
bindingExpression.UpdateSource();
}
}

Resources