When you activate an application, a textbox with text "hello" will appear.
My question is:
When you click on the textbox in order to make input data, I want to remove the text automatically in XAML code, how do I do it?
Handle the UIElement.GotFocus event, and in the handler, clear the text. You'll also want to remove the handler, so that if you click on the TextBox a second time you don't lose what you've already entered.
Something like this:
XAML:
<TextBox Text="Hello" GotFocus="TextBox_GotFocus" />
Code-behind:
public void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.Text = string.Empty;
tb.GotFocus -= TextBox_GotFocus;
}
A XAML implementation that requires no code-behind. This is copied from the template of a custom control I built, and you'd probably want to make this a custom control yourself.
The basic idea is that there are two TextBoxes in a Grid. The top one is the actual control that the user interacts with, but it's invisible (its 'Opacity' is zero) unless it contains text or has the focus. The bottom one contains the prompt text. It will only be visible when the TextBox on top of it is not, and it will never get the focus.
You'll probably have to mess around with the binding on the editable TextBox, but this should get you started.
<Grid>
<TextBox Text="This is the prompt text"
FontStyle="Italic"
Foreground="LightGray"
Focusable="False">
</TextBox>
<TextBox Text="{Binding TextProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Focusable="True">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Opacity"
Value="1" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused"
Value="False" />
<Condition Property="Text"
Value="" />
</MultiTrigger.Conditions>
<Setter Property="Opacity"
Value="0" />
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
You have to implement both GetFocus and LostFocus events. In this way you can set the default text back in lost focus event if no text is entered.
private const string defaultText = "Hello";
private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
myTextBox.Text = myTextBox.Text == defaultText ? string.Empty : myTextBox.Text;
}
private void myTextBox_LostFocus(object sender, RoutedEventArgs e)
{
myTextBox.Text = myTextBox.Text == string.Empty ? defaultText : myTextBox.Text;
}
To expound upon Donut's answer so that your textbox will keep the text a user inputs unless it's purely whitespace, here's a solution that I use:
XAML
<TextBox Text="Search..."
Width="250"
Foreground="LightGray"
GotFocus="TextBox_GotFocus"
LostFocus="TextBox_LostFocus" />
C#
void TextBox_GotFocus( object sender, RoutedEventArgs e )
{
TextBox box = sender as TextBox;
box.Text = string.Empty;
box.Foreground = Brushes.Black;
box.GotFocus -= TextBox_GotFocus;
}
void TextBox.LostFocus( object sender, RoutedEventArgs e )
{
TextBox box = sender as TextBox;
if( box.Text.Trim().Equals( string.Empty ) )
{
box.Text = "Search...";
box.Foreground = Brushes.LightGray;
box.GotFocus += TextBox_GotFocus;
}
}
I just did this:
XAML:
<TextBox Name="Filename"
Grid.Column="0"
Height="23"
Margin="10,9,0,0"
Text="Enter Export Filename here"
Width="193"
GotFocus="Filename_GotFocus"
/>
Code behind:
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.Text = "";
}
you can use Tap method also , it is also working
private void tb1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
tb1.Text = "";
}
Please don't over complicate the answer several ways to skin a cat but,
less code the better I would presume.
Petermac's option is the way to go for me.
Add "GotFocus" in the main Xaml window to the control eg."textbox"
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.Text = "";
}
or I like this option
private void Filename_GotFocus(object sender, RoutedEventArgs e)
{
Filename.clear();
}
the question asked was just to empty the textbox.
I want to update Donut's answer.(applicable for windows 8)
Code behind code be
public void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
if(tb.Text != "SOME DEFAULT TEXT")
{
String persentContentWithDefaultString = t.Text as string;
tb.Text = persentContentWithDefaultString[0].ToString();
// set cursor position
tb.Select(1, 0);
tb.GotFocus -= TextBox_GotFocus;
}
}
Actully in my page , there were two textbox and one button. [Username,pass,and click button]. By default , focus goes to my first textbox and User was not able to see the default text.
Related
I have build a dynamic UserControl from an ObservableCollection as follows...
public static ObservableCollection<Model.Model.ControleData> ListControleMachine = new ObservableCollection<Model.Model.ControleData>();
public Genkai(string Autorisation) {
InitializeComponent();
DataContext = this;
icTodoList.ItemsSource = ListControleMachine;
Model.Model.ControleData v = new Model.Model.ControleData();
v.ComputerName = "M57095";
v.ImportSource = "LOAD";
ListControleMachine.Add(v);
}
XAML
<ItemsControl x:Name="icTodoList" ItemsSource="{Binding ListControleMachine}" >
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:ControlMachineII}">
<local:ControlMachineII />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But how can I access the DataContext from C# code?
For example say I want to delete the UserControl with a close button in itself, I need at least access ControleData.ComputerName value then remove it from Mainform.ListControleMachine.
I can't find the best practice for achieve this and play with my data in UserControl code.
The remove button code is like this i think (with hard coded value)
Genkai.ListControleMachine.Remove(Genkai.ListControleMachine.Where(X => X.ComputerName == "M57095").Single());
i finaly found that my DataContext was not yet initialized at start that why i got error so i had to wait for the datacontext first: here code for correction
public ControlMachineII()
{
InitializeComponent();
DataContextChanged += new DependencyPropertyChangedEventHandler(ControlMachineII_DataContextChanged);
}
private void ControlMachineII_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
string compname = (this.DataContext as Model.Model.ControleData).ComputerName;
Console.WriteLine("DataContext initialized computername :" +compname);
}
I saw you posted same question today with some more data. I'm going to present the solution using that data.
Solution 1 :
Use Tag property of button like below:
<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0"
VerticalAlignment="Top" Width="119" Click="Button_Click" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
Event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
List<object> list = (button.Tag as ItemsControl).ItemsSource.OfType<TodoItem>().ToList<object>();
list.Remove(button.DataContext);
(button.Tag as ItemsControl).ItemsSource = list;
}
Solution 2:
More elegant solution:
Create this Style in your MainWindow:
<Window.Resources>
<Style TargetType="Button">
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
</Window.Resources>
So now the Handler of any Button Click event in any MainWindow's descendant Button Control is in the MainWindow.xaml.cs.
Then place the handler method in MainWindow.xaml.cs and change the handler like below:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
items.Remove(button.DataContext as TodoItem);
icTodoList.ItemsSource = null;
icTodoList.ItemsSource = items;
}
I have a simple datagrid that display bidimensional data.
I have tried it in a test project and the result is nice.
Here is the xmal:
<Grid >
<DataGrid Name="dg" Margin="50" FontSize="26" CellEditEnding="dg_CellEditEnding" BeginningEdit="dg_BeginningEdit" LoadingRow="DataGrid_LoadingRow" EnableRowVirtualization="False" AutoGeneratingColumn="dg_AutoGeneratingColumn"/>
</Grid>
and the relevant event code:
private void DataGrid_LoadingRow(object sender, System.Windows.Controls.DataGridRowEventArgs e)
{
e.Row.Header = "R" + ((e.Row.GetIndex()) + 1).ToString();
}
private void dg_AutoGeneratingColumn(object sender, System.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e)
{
string str = e.PropertyName;
int num = int.Parse(e.PropertyName);
e.Column.Header = "C" + (num + 1).ToString();
}
then I have to put it in my real project which is a styled window.
So I put the same very easy xaml (adding background and foreground fore here I have a gradient background) so that the xamls is:
<Grid >
<DataGrid Name="dtgNests" Margin="50" FontSize="26" Background="White" Foreground="Black" HeadersVisibility="All" CellEditEnding=" dg_CellEditEnding" BeginningEdit="dg_BeginningEdit" LoadingRow="DataGrid_LoadingRow" EnableRowVirtualization="False" AutoGeneratingColumn="dg_AutoGeneratingColumn"/>
</Grid>
and the effect is:
so in short the FOREGROUND is not being set in any part. That is:
cells
row headers
column headers
so nowhere.
Can anyone tell me why?
thank you in advance
Patrick
In a WPF DataGrid, all cell-related design needs to be set as the Column's ElementStyle, which overrides the foreground set in your Grid. Try the following:
In your XAML resources:
<Style x:Key="BlackCellStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Black" />
</Style>
In your AutoGeneratingColumn handler:
private void dg_AutoGeneratingColumn(object sender, System.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e)
{
string str = e.PropertyName;
int num = int.Parse(e.PropertyName);
e.Column.Header = "C" + (num + 1).ToString();
e.Column.ElementStyle = FindResource("BlackCellStyle") as Style;
}
This will apply the foreground directly to your cells
WPF- Selection Brush is not working, I am selecting 'H' in my case but it is not working.
Here is my code :
XAML :
<TextBox Text="Hello" Height="49" Name="textBox2" Width="547" />
C#
textBox2.SelectionStart = 0;
textBox2.SelectionLength = 1;
textBox2.SelectionBrush = Brushes.Red;
Try this
textBox2.Focus();
textBox2.SelectionStart = 0;
textBox2.SelectionLength = 1;
textBox2.SelectionBrush = Brushes.Red;
An alternative solution is to trick the TextBox into thinking it has not lost focus. This way, you're not actually moving focus back to the TextBox.
For this to work, you'd have to set focus on the TextBox at least once, like when the user enters the initial text, or by calling textBox2.Focus() from the constructor.
Markup:
<TextBox Height="49" x:Name="textBox2" LostFocus="TextBox2_OnLostFocus" />
Code-behind:
private void TextBox2_OnLostFocus(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
public partial class MultiTexbox_2 : Window
{
Control texbox_full_details = null; //get all textbox property and method in when gotfocused
Control button_full_details; //get all button property and method in when click event
Button keyboard_button; //behave like button
public MultiTexbox_2()
{
this.InitializeComponent();
// Insert code required on object creation below this point.
}
private void btn_a_Click(object sender, RoutedEventArgs e)
{
button_full_details = (Control)sender;
all_in_one();
//var caretIndex = txt_diplay_1.CaretIndex;
//txt_diplay_1.Text = txt_diplay_1.Text.Insert(caretIndex, btn_a.Content.ToString());
//txt_diplay_1.Focus();
//txt_diplay_1.CaretIndex = caretIndex + 1;
}
private void btn_b_Click(object sender, RoutedEventArgs e)
{
button_full_details = (Control)sender;
all_in_one();
}
private void btn_c_Click(object sender, RoutedEventArgs e)
{
button_full_details = (Control)sender;
all_in_one();
}
private void txt_diplay_1_GotFocus(object sender, RoutedEventArgs e)
{
texbox_full_details = (Control)sender;
}
private void txt_diplay_2_GotFocus(object sender, RoutedEventArgs e)
{
texbox_full_details = (Control)sender;
}
public void all_in_one()
{
keyboard_button = button_full_details as Button;
if (texbox_full_details != null)
{
//TextBox tb = texbox as TextBox;
//tb.Text += btn.Content;
TextBox txt_box = texbox_full_details as TextBox;
var caret_index = txt_box.CaretIndex;
txt_box.Text = txt_box.Text.Insert(caret_index, keyboard_button.Content.ToString());
txt_box.Focus();
txt_box.CaretIndex = caret_index + 1;
}
}
}
It's output will be like this
But need output like this
When click the button,it's content will bind in textbox.on that time the currently binded textbox text's background color,font color and font size should change.what should i do to get that kind of output.Please help me.
Look into SelectedText, SelectionStart and SelectionLength. http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.aspx
tb.SelectionStart = tb.Length - 1;
tb.SelectionLength = 1;
Ok so you want that, on a given condition, your TextBox text Zoom.
So First create a class with two properties : EditedText and IsZoomed for instance :
public class ZoomableText
{
public string EditedText { get; set; }
public Boolean IsZoomed { get; set; }
}
Then use Xaml : use a style with a DataTrigger on IsZoomed, and change the text aspect you want when IsZoomed is true. You might declare this style inside your window resources or in your application resources. Example :
<Style TargetType="TextBox" x:Key="LargerWhenFocusedTextBox">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsZoomed}" Value="True">
<Setter Property="FontSize" Value="14" />
<Setter Property="FontWeight" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
To use it, just do something like :
<StackPanel >
<TextBox Text="{Binding EditedText}"
Style="{StaticResource LargerWhenFocusedTextBox}" />
<ToggleButton IsChecked="{Binding IsZoomed}" Content="Zoomed?" />
</StackPanel >
Where you will set the DataContext of the StackPanel to an instance of a ZoomableText Object.
You might want to make the ZoomableText Object implements INotifyPropertyChanged on its properties.
For the curret change, handle the Checked event of the ToggleButton.
Note that if you don't give a Key to the style, it will be applied automatically to all your TextBoxes.
I have this requirement where I need to focus the first element inside the expander when the user press tab.
Currently (default behavior) the focus goes to the expander, I've tried to focus the first element of the expander by creating a focus event handler in the expander like this:
private void ExpanderGotFocus(object sender, RoutedEventArgs e)
{
var expander = (Expander) sender;
if (!expander.IsExpanded)
{
expander.IsExpanded = true;
this._someText.Focus();
}
}
Which doesn't work.
I've also tried to give the focus the the next element:
var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
var keyboardFocus = Keyboard.FocusedElement as UIElement;
keyboardFocus.MoveFocus(tRequest);
But only works the second time ( when the expander has been at least opened once )
I've tried to put this in a thread and some other crazy ideas.
How can I give focus to the first element inside an expander? ( the first time the expander is closed )
I tried several ways and none of them worked, basically the problem is the TextBox is still rendering when the expander is expanding ( to early ).
So instead what I've found is to add the IsVisibleChanged event to the textbox so when the expander finished the textbox become visible and request the focus
XAML
<Expander GotFocus="ExpanderGotFocus">
<Expander.Header>
<TextBlock Text="{x:Static Client:Strings.XYZ}" />
</Expander.Header>
<Expander.Content>
<StackPanel>
<TextBox IsVisibleChanged="ControlIsVisibleChanged" Name="txtBox" />
</StackPanel>
</Expander.Content>
</Expander>
Code behind
private void ExpanderGotFocus(object sender, RoutedEventArgs e)
{
var expander = (Expander) sender;
if (!expander.IsExpanded )
{
expander.IsExpanded = true;
}
}
private void ControlIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Keyboard.Focus((IInputElement)sender);
}
Check with the following,
XAML code:
<StackPanel>
<Expander Header="Expander"
Name="expander"
Collapsed="OnCollapsed"
IsExpanded="True" >
<StackPanel>
<TextBox Text="Text1" Name="textBox1" />
<TextBox Text="Text2" Name="textBox2" />
<TextBox Text="Text3" Name="textBox3" />
</StackPanel>
</Expander>
<TextBox Text="Text4" Name="textBox4" />
</StackPanel>
in the code behind:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.Loaded += delegate
{
textBox2.Focus();
};
}
private void OnCollapsed(object sender, RoutedEventArgs e)
{
var element = Keyboard.FocusedElement;
if (element != null)
{
//now is the ToggleButton inside the Expander get keyboard focus
MessageBox.Show(element.GetType().ToString());
}
//move focus
Keyboard.Focus(textBox4);
}
}