I need a feature in silverlight text box, simillar functionality as in Ask Question "Title" textbox in stalkoverflow. When there's no text in textbox then it should display "Search". When user clicked on the textbox then textbox text should be empty and in textbox lost focus if the text is empty then show "Search". I wrote the following code, but is there any code which handles all possible conditions?
private void txtAvailable_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
txtAvailable.Text = "";
}
private void txtAvailable_LostFocus(object sender, RoutedEventArgs e)
{
if (txtAvailable.Text.Trim() == "")
txtAvailable.Text = "Search";
}
You could use the Textbox GotFocus and LostFocus events - they should be generic enough to cover off all of your potentials..
The specialness comes when you want to search on every keystroke - you have to enable and disable searching on those events.
private bool IsBusy
{
get;
set;
}
private bool CanSearch
{
get;
set;
}
public Constructor()
{
InitializeComponent();
this.IsBusy = false;
txtSearch.GotFocus += new RoutedEventHandler( txtSearch_GotFocus );
txtSearch.LostFocus += new RoutedEventHandler( txtSearch_LostFocus );
txtSearch.KeyUp += new System.Windows.Input.KeyEventHandler( txtSearch_KeyUp );
txtSearch.Text = "Search »";
}
private void txtSearch_LostFocus( object sender, RoutedEventArgs e )
{
if( string.IsNullOrEmpty( txtSearch.Text ) )
{
CanSearch = false;
txtSearch.Text = "Search »";
}
}
private void txtSearch_GotFocus( object sender, RoutedEventArgs e )
{
txtSearch.Text = string.Empty;
CanSearch = true;
}
private void OnFilterCommand()
{
try
{
if( !IsBusy && CanSearch )
{
AppMessages.FilterAssetMessage.Send( txtSearch.Text );
}
}
catch( Exception ex )
{
// Notify user if there is any error
AppMessages.RaiseErrorMessage.Send( ex );
}
}
private void txtSearch_KeyUp( object sender, System.Windows.Input.KeyEventArgs e )
{
OnFilterCommand();
}
If you're familiar with WPF and the differences between WPF and Silverlight, take a look at the WatermarkTextBox in the extended WPF toolkit:
http://wpftoolkit.codeplex.com/wikipage?title=WatermarkTextBox&referringTitle=Home
The source is available, so you could try porting that control to Silverlight.
Related
In a WPF form .NET framework, I'm trying to achieve the following (seemingly) simple task:
I have 3 buttons and 3 textboxes:
Button 1
Textbox1
Button 2
Textbox2
Button 3
Textbox3
If I click button 1, I want textbox 1 to read true and the other 2 false. If I click button 2, I want textbox 2 to show true and the others false and the same for button 3 and textbox 3 respectively.
I thought I could achieve this by setting the value of all of the Booleans to either true or false depending on the button that has been clicked using the click event, but don't get the expected result
using System;
using System.Windows;
using System.Threading;
using System.Windows.Threading;
namespace WPF_Test
{
public partial class MainWindow : Window
{
bool value1;
bool value2;
bool value3;
public MainWindow()
{
InitializeComponent();
if (value1 == true)
{
textbox1.Text = value1.ToString();
} else if (value2 == true){
textbox2.Text = value2.ToString();
} else if (value3 == true){
textbox3.Text = value3.ToString();
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
value1 = true;
value2 = false;
value3 = false;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
value1 = false;
value2 = true;
value3 = false;
}
private void button3_Click(object sender, RoutedEventArgs e)
{
value1 = false;
value2 = false;
value3 = true;
}
}
}
Any idea what I might be missing?
referencing Rekshino's comment:
Just move the code in the constructor after InitializeComponent to the separate method and then call it at the bottom each Button.Click event handler. – Rekshino
however, my limited knowledge does not certify that this is the 'best' version so for this I refer to D M's answer as well
In order to update the UI in WPF by binding to a value in the code behind, you need to change the fields to properties and implement the INotifyPropertyChanged interface. There's a really good answer on how to do this by Marc Gravell.
public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool _value1;
public bool value1
{
get => _value1;
set => SetField(ref _value1, value);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
value1 = true;
}
// Implementation of INotifyPropertyChanged with a
// SetField helper method to ensure you're only
// notifying when a value actually changes.
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged(string? propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
I'm making a custom behavior for Telerik's RadGridView.
When this behavior is attached and its PropertyName is set to same property as specified by
DataMemberBinding value of some of the GridViewCheckBoxColumn of the grid, then toggling the checkbox in that column will apply same checkbox state to all selected rows (but only to the same column).
That happens in the ApplyToAllSelected method, namely in gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked); line. The visuals are working as expected, and all checkbox values are updated on screen.
The Problem is that the binding source is not updated for those rows. Only for the one where click happened. GridViewCheckBox.IsChecked dependency property does not seem to be bound directly to the datacontext's property, so gvcb.GetBindingExpression(GridViewCheckBox.IsChecked) returns null.
The Question: how to update source after setting checkbox state?
public sealed class CheckAllSelectedBehavior : Behavior<RadGridView>
{
public event EventHandler Toggled;
public string PropertyName { get; set; }
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.PreparingCellForEdit += this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded += this.AssociatedObject_CellEditEnded;
}
protected override void OnDetaching()
{
this.AssociatedObject.PreparingCellForEdit -= this.AssociatedObject_PreparedCellForEdit;
this.AssociatedObject.CellEditEnded -= this.AssociatedObject_CellEditEnded;
base.OnDetaching();
}
private void AssociatedObject_CellEditEnded(object sender, GridViewCellEditEndedEventArgs e)
{
if (e.Cell.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked -= this.Cb_Checked;
cb.Unchecked -= this.Cb_Unchecked;
}
}
private void AssociatedObject_PreparedCellForEdit(object sender, GridViewPreparingCellForEditEventArgs e)
{
if (e.Column.UniqueName == this.PropertyName && e.EditingElement is CheckBox cb)
{
cb.Checked += this.Cb_Checked;
cb.Unchecked += this.Cb_Unchecked;
}
}
private void Cb_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(false);
}
private void Cb_Checked(object sender, System.Windows.RoutedEventArgs e)
{
this.ApplyToAllSelected(true);
}
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
var row = this.AssociatedObject.GetRowForItem(item);
var cell = row.GetCellFromPropertyName(this.PropertyName);
if (cell.Content is GridViewCheckBox gvcb)
{
gvcb.SetCurrentValue(GridViewCheckBox.IsCheckedProperty, isChecked);
}
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
}
Using reflection to set the value on viewmodel property seems to work. Modify the ApplyToAllSelected method like follows:
private void ApplyToAllSelected(bool isChecked)
{
foreach (var item in this.AssociatedObject.SelectedItems)
{
this.SetProperty(item, isChecked);
}
this.Toggled?.Invoke(this, EventArgs.Empty);
}
private void SetProperty(object target, bool isChecked)
{
var prop = target.GetType().GetProperty(
this.PropertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
prop.SetValue(target, isChecked);
}
I have 6 Textbox in a registration form with some preset text.
When I click in the Textbox for Name then preset text Enter your full name should disappear...If I then click on the Textbox for Email without writing anything in Name Textbox, then Enter your full name should appear again. This event should happen for all my Textbox, but their should be different text in each Textbox...Not Enter your full name in all of them. Can someone please help me with this?
The code I have right now makes it possible to clear the Textbox as I click on them, using GotFocus event.
private void textBox1_GotFocus(Object sender, EventArgs e)
{
textBox1.Clear();
}
In the textboxes, I have preset text....I want that exact preset text for each textbox to come back whenever I am clicking outside that Textbox.
I've heard something about a "Placeholder" ?
Here's how it looks now with an extra constructor. I can't figure out what I'm doing wrong?
public partial class CustomTextbox : TextBox
{
private const string _text = #"Enter your full name";
private bool _isEmpty = true;
public CustomTextbox()
{
base.ForeColor = SystemColors.GrayText;
Text = _text;
Leave += LeaveTextBox;
Enter += EnterTextBox;
TextChanged += TextChangedTextBox;
}
public CustomTextbox(string tempText)
{
base.ForeColor = SystemColors.GrayText;
Text = tempText;
Leave += LeaveTextBox;
Enter += EnterTextBox;
TextChanged += TextChangedTextBox;
}
Try creating a custom Class inheriting from Textbox. To achieve this, create a new Usercontrol. Delete the base class name and place Textbox there. Delete anything in designer if giving compilation error. Build your project. You should see a new control in toolbox. Use it and you are good to go. Here is the code for Usercontol.cs
public partial class CustomTextbox : TextBox
{
private const string _text = #"Enter your full name";
private bool _isEmpty = true;
public CustomTextbox()
{
InitializeComponent();
base.ForeColor = SystemColors.GrayText;
Text = _text;
Leave += LeaveTextBox;
Enter += EnterTextBox;
TextChanged += TextChangedTextBox;
}
private void TextChangedTextBox(object sender, EventArgs e)
{
_isEmpty = string.IsNullOrEmpty(Text);
}
public override sealed string Text
{
set
{
base.Text = value;
}
}
private void LeaveTextBox(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(Text))
{
Text = _text;
_isEmpty = true;
base.ForeColor = SystemColors.GrayText;
}
else
{
_isEmpty = false;
}
}
private void EnterTextBox(object sender, EventArgs e)
{
if (_isEmpty)
Text = string.Empty;
base.ForeColor = SystemColors.ControlText;
}
}
Let me know if you need any further information. As a not, you can also make _text as a public property and use it to set the desired text property.
Hope it helps.
I solved my problem!
Thanks to #rapsalands for providing the code.
I have now modified it for my needs.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
}
public partial class CustomTextbox : TextBox
{
private string defaultText;
public string DefaultText
{
get { return defaultText; }
set { defaultText = value; }
}
private bool _isEmpty = true;
public CustomTextbox(string myText)
{
base.ForeColor = SystemColors.GrayText;
this.Text = myText;
this.DefaultText = myText;
Leave += LeaveTextBox;
Enter += EnterTextBox;
TextChanged += TextChangedTextBox;
}
private void TextChangedTextBox(object sender, EventArgs e)
{
_isEmpty = string.IsNullOrEmpty(Text);
}
public override sealed string Text
{
set
{
base.Text = value;
}
}
private void LeaveTextBox(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(Text))
{
Text = defaultText;
_isEmpty = true;
base.ForeColor = SystemColors.GrayText;
}
else
{
_isEmpty = false;
}
}
private void EnterTextBox(object sender, EventArgs e)
{
if (_isEmpty)
Text = string.Empty;
base.ForeColor = SystemColors.ControlText;
}
}
}
I have an attached property called "SelectAllOnFocus". Values of true/false.
public static class TextBoxProps
{
private static void MyTextBoxKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
((TextBox)sender).Text = string.Empty;
}
}
public static void SetSelectAllOnFocus(DependencyObject dependencyObject, bool selectAllOnFocus)
{
if (!ReferenceEquals(null, dependencyObject))
{
dependencyObject.SetValue(SelectAllOnFocus, selectAllOnFocus);
}
}
public static bool GetSelectAllOnFocus(DependencyObject dependencyObject)
{
if (!ReferenceEquals(null, dependencyObject))
{
return (bool)dependencyObject.GetValue(SelectAllOnFocus);
}
else
{
return false;
}
}
private static void OnSelectAllOnFocus(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool selectAllOnFocus = (bool)e.NewValue == true;
var theTextBox = d as TextBox;
if (selectAllOnFocus && theTextBox != null)
{
theTextBox.PreviewMouseDown -= MyTextBoxMouseEnter; theTextBox.PreviewMouseDown += MyTextBoxMouseEnter;
}
}
private static void MyTextBoxMouseEnter(object sender, MouseEventArgs e)
{
((TextBox)sender).SelectAll();
e.Handled = false;
}
public static readonly DependencyProperty SelectAllOnFocus
= DependencyProperty.RegisterAttached("SelectAllOnFocus", typeof(bool), typeof(TextBoxEscapeProperty),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnSelectAllOnFocus)));
}
What happens is the following:
The PreviewMouseDown event gets triggered.
The MyTextBoxMouseEnter method gets called.
The SelectAll() Method gets called.
When I do a "watch" on ((TextBox)sender).SelectedText, the value is correct (meaning whatever is in the textbox is showing up as selectedText).
The textbox itself is unchanged. No text is selected.
This is part of a general WPF style. All textboxes in the application should receive this property and it's associated behavior.
I'm stumped. Any ideas?
Thanks
What happens if you call ((TextBox)sender).UpdateLayout(); immediately after the SelectAll command? Or maybe you need to set the Keyboard focus to the text box.
It might be a better option to use something like this, which works if the text box is being selected with the mouse or the keyboard. (You'll need to modify it to check your "SelectAllOnFocus" property)
In your App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
// Select the text in a TextBox when it receives focus.
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(SelectivelyIgnoreMouseButton));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotKeyboardFocusEvent, new RoutedEventHandler(SelectAllText));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.MouseDoubleClickEvent, new RoutedEventHandler(SelectAllText));
base.OnStartup(e);
}
void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
// Find the TextBox
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);
if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
// If the text box is not yet focused, give it the focus and
// stop further processing of this click event.
textBox.Focus();
e.Handled = true;
}
}
}
void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox != null)
textBox.SelectAll();
}
how to create a watermark text box in winForm
i want to use in my applications login screen
if you want to make it simple, you could do this :
string xyz = "Enter User Name Here..";
private void textBox_Leave(object sender, EventArgs e)
{
{
if (textBox.Text.Length.Equals(0))
{
textBox.Text = xyz;
}
}
}
private void textBox_Click(object sender, EventArgs e)
{
{
if (textBox.Text.Equals(xyz))
{
textBox.Clear();
}
}
}
and do put following lines to your form_load event :
textBox.Text = xyz;
textBox.Select(textBox.Text.Length, 0);