c# Format all TextBox when lostfocus - c#

I created public void that formating all the textbox in grid to currency
My code
public void FormatinTextBox()
{
foreach (Control ctrl in MainGrid.Children)
{
if (ctrl.GetType() == typeof(TextBox))
{
double amount = 0.0d;
if (Double.TryParse(((TextBox)ctrl).Text, NumberStyles.Currency, null, out amount))
((TextBox)ctrl).Text = amount.ToString("C");
else
((TextBox)ctrl).Text = String.Empty;
}
}
}
and it's working perfect if i put this code to event handler of MainGrid_Loaded.
but i want to run this code for each time i leave textbox (lostFocus).
i prefer to fire this code with xaml on each textbox, i dont know if it possible to do that. this is my code in xaml for one of my textbox
<TextBox x:Name="Nose" HorizontalAlignment="Left" Height="24" Margin="710,209,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" Width="110" BorderThickness="0,0,0,1" Text="100" LostFocus="Nose_LostFocus"/>
if it's not possible, how can i run this code on back code
private void Nose_LostFocus(object sender, RoutedEventArgs e)
{
}

If you bind the Text property to a source property, you could apply a StringFormat to the binding:
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent();
Nose.DataContext = this;
}
public decimal? Text { get; set; }
}
XAML:
<TextBox x:Name="Nose" Text="{Binding Text, StringFormat=C}"/>
But if you wan't some custom logic, you could use an event handler. You would implement it pretty much the same way as you did before:
private void Nose_LostFocus(object sender, RoutedEventArgs e)
{
TextBox textBox = (TextBox)sender;
double amount;
textBox.Text = (double.TryParse(textBox.Text, out amount)) ? amount.ToString("C") : string.Empty;
}

Related

Get content of a previous tab on SelectionChanged event

Im trying to get the previous selected tabs content when it is changed to another in a TabControl. For this i subscribe to the SelectionChanged event like so:
tabControl.SelectionChanged += getPreviousData
Then the getPreviousData method looks like this:
private void getPreviousData(object sender, SelectionChangedEventArgs e)
{
e.RemovedItems[0].something
}
Im a little unsure as to how i grab the previous tab content. The previous tab has a textbox control that i need to get the name of, when i change the tab. How can i accomplish that?
Assuming you have a XAML like that
<TabControl x:Name="tabControl" SelectionChanged="tabControl_SelectionChanged">
<TabItem Header="TabItem">
<Grid Background="#FFE5E5E5">
<TextBox Width="100" Height="23"></TextBox>
</Grid>
</TabItem>
<TabItem Header="TabItem">
<Grid Background="#FFE5E5E5">
<TextBlock x:Name="TextBlock"></TextBlock>
</Grid>
</TabItem>
</TabControl>
First option
Then you can access children of removed TabItem using this code
private void tabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count != 0)
{
var tabItem = (TabItem)e.RemovedItems[0];
var content = (Grid)tabItem.Content;
var textBox = content.Children.OfType<TextBox>().First();
var text = textBox.Text;
}
}
Second option
You can name your textbox
<TextBox x:Name="TextBoxInFirstTab" Width="100" Height="23"></TextBox>
And access it using his name
var text2 = TextBoxInFirstTab.Text;
Third option
Use MVVM, check this answer MVVM: Tutorial from start to finish?
I am going to provide a simple sample, without any framework, but I suggest you to use anyone, like MVVM Light ToolKit.
Create a View Model
Implement the INotifyPropertyChanged interface
Create a property that will hold your text value, and in the set call the OnPropertyChanged
public class MyViewModel : INotifyPropertyChanged
{
private string _textInFirstTab;
public string TextInFirstTab
{
get { return _textInFirstTab; }
set
{
_textInFirstTab = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then in your Window constructor, set the DataContext property from Window, to a new instance for your MyViewModel.
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
Then in your XAML set the Text attribute with a Binding expression
<TextBox x:Name="TextBox" Width="100" Height="23" Text="{Binding TextInFirstTab}"></TextBox>
And in your tabControl_SelectionChanged event, you can access the value like that:
private void tabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.RemovedItems.Count != 0)
{
var myViewModel = (MyViewModel)DataContext;
var text = myViewModel.TextInFirstTab;
}
}
If it is switching between existing tabs which you are after, then I would suggest simply storing the index of the selected tab in a class variable.
Sample code looks like this:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// variable to store index of tab which was most recently selected
private int lastSelectedTabIndex = -1;
public Form1()
{
InitializeComponent();
// initialise the last selected index
lastSelectedTabIndex = tabControl1.SelectedIndex;
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
// sanity check: if something went wrong, don't try and display non-existent tab data
if (lastSelectedTabIndex > -1)
{
MessageBox.Show(string.Format("Previous tab: {0} - {1}", lastSelectedTabIndex, tabControl1.TabPages[lastSelectedTabIndex].Text));
}
// store this tab as the one which was most recently selected
lastSelectedTabIndex = tabControl1.SelectedIndex;
}
}
}
This was written and tested in a simple application with one form and a TabControl added. No changes were made to the default properties.
You will, of course, have to hook into the event handler. I did so by double-clicking it in the IDE, but you could also hook in manually by adding:
this.tabControl1.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged);
to the form constructor, called "Form1()" in the example code.
Getting the name of a textbox is an unusual thing to want to do. May I ask what you are trying to achieve? There's probably a better way to do it than trying to determine the name of a control.

Windows Phone TwoWay binding not working

Actually the 2 way binding works, but there is a problem.
I have a button on the appbar. Also I have a textbox with TwoWay binding. Now, if I am typing in the textbox, and I remove focus from the textbox (close the keyboard by pressing back key), then the Property to which the textbox text is binded gets updated.
But, if I press the AppBar Button without closing the keyboard, the property does not get updated.
Is there a simple solution to this problem?
All help is greatly appreciated.
Thank You!
Edit:
I tried this.focus on the AppBar button click, but still no luck
Edit 2:
Here is my code-
<StackPanel>
<TextBlock Text="Title" FontSize="{StaticResource PhoneFontSizeMediumLarge}" Margin="15,0,0,0"/>
<TextBox Name="TitleTB" Text="{Binding Title, Mode=TwoWay}" />
<TextBlock Text="Description" FontSize="{StaticResource PhoneFontSizeMediumLarge}" Margin="15,0,0,0"/>
<TextBox Name="DescriptionTB" Text="{Binding Description, Mode=TwoWay}" AcceptsReturn="True" MaxHeight="300" VerticalScrollBarVisibility="Auto" />
</StackPanel>
.cs code-
public CreateTaskPage()
{
InitializeComponent();
M1 = new MyClass { Description = "Description", Title = "title1" };
this.DataContext = M1;
}
private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
//save - I change the text in the textbox from title1 to title123 suppose
// But it still shows title1 if I click the appbar button without closing the keyboard
this.Focus();
MessageBox.Show(M1.Title);
}
Edit 3:
MyClass code-
public class MyClass : INotifyPropertyChanged
{
private string title;
private string description;
public string Title
{
get { return title; }
set
{
title = value;
OnPropertyChanged("Title");
}
}
public string Description
{
get { return description; }
set
{
description = value;
OnPropertyChanged("Description");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
Try this:
private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
BindingExpression expression = TitleTB.GetBindingExpression(TextBox.TextProperty);
MessageBox.Show("Before UpdateSource, Test = " + M1.Title);
expression.UpdateSource();
MessageBox.Show("After UpdateSource, Test = " + M1.Title);
}
For more Refrence about binding you can go here Data binding for Windows Phone
Just to make sure, did you properly declare the property of MyClass like below?
class MyClass {
public String Description { get; set; }
public String Title { get; set; }
}
Why dont you shift the focus from textbox to some other control in the click event of the ApplicationBarIconButton.

How to get lable name in dynamically?

<Grid x:Name="LayoutRoot">
<TextBox x:Name="txt_diplay_1" HorizontalAlignment="Left" Height="42" Margin="155,78,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="103.5" GotFocus="txt_diplay_1_GotFocus" />
<TextBox x:Name="txt_diplay_2" Height="42" Margin="297,78,239.5,0" TextWrapping="Wrap" VerticalAlignment="Top" GotFocus="txt_diplay_2_GotFocus" />
<Button x:Name="btn_a" Content="A" HorizontalAlignment="Left" Height="40" Margin="155,147,0,0" VerticalAlignment="Top" Width="73" Click="btn_a_Click" />
<Button x:Name="btn_b" Content="B" Height="40" Margin="237,147,0,0" VerticalAlignment="Top" Click="btn_b_Click" HorizontalAlignment="Left" Width="73" />
<Button x:Name="btn_c" Height="40" Margin="0,147,239.5,0" VerticalAlignment="Top" HorizontalAlignment="Right" Width="73" Click="btn_c_Click" >
<Grid Height="30.833" Width="61.5">
<Label x:Name="lbl_1" Content="1" Margin="22.498,6.5,19.501,2.166"/>
<Label x:Name="lbl_2" Content="!" HorizontalAlignment="Right" Margin="0,-4.422,0,13.088" Width="19.501"/>
</Grid>
</Button>
</Grid>
The design will be like this
public partial class MainWindow : Window
{
Control TexboxDetails = null;
Control ButtonDetails;
Button BehaveButton;
public MainWindow()
{
this.InitializeComponent();
}
private void btn_a_Click(object sender, RoutedEventArgs e)
{
ButtonDetails = (Control)sender;
all_in_one();
}
private void btn_b_Click(object sender, RoutedEventArgs e)
{
ButtonDetails = (Control)sender;
all_in_one();
}
private void btn_c_Click(object sender, RoutedEventArgs e)
{
}
private void txt_diplay_1_GotFocus(object sender, RoutedEventArgs e)
{
TexboxDetails = (Control)sender;
}
private void txt_diplay_2_GotFocus(object sender, RoutedEventArgs e)
{
TexboxDetails = (Control)sender;
}
public void all_in_one()
{
BehaveButton = ButtonDetails as Button;
if (TexboxDetails != null)
{
TextBox BehaveTextbox = TexboxDetails as TextBox;
var caret_index = BehaveTextbox.CaretIndex;
BehaveTextbox.Text = BehaveTextbox.Text.Insert(caret_index, BehaveButton.Content.ToString());
BehaveTextbox.Focus();
BehaveTextbox.CaretIndex = caret_index + 1;
}
}
}
With above code i can get Button name dynamically when i click that button.
In above figure one button(btn_c) has two labels. now i want get that separate labels name dynamcially when i click button(btn_c).
You can get them like this (inside the btn_c click handler):
var btn_c = (Button)sender;
Grid grid = (Grid)btn_c.Content;
Label label1 = (Label)grid.Children[0];
string name1 = label1.Name;
Your whole design could really use some rework. Take a look at this code: (notice the reduced number of event handlers; you'll need to modify the XAML to use these)
public partial class MainWindow : Window
{
TextBox LastFocusedTextBox;
public MainWindow()
{
this.InitializeComponent();
}
private void btn_Click(object sender, RoutedEventArgs e)
{
InsertButtonContent((Button)sender);
}
private void txt_diplay_GotFocus(object sender, RoutedEventArgs e)
{
LastFocusedTextBox = (TextBox)sender;
}
public void InsertButtonContent(Button button)
{
if (LastFocusedTextBox != null)
{
string buttonContentString = button.Content as string;
if (string.IsNullOrEmpty(buttonContentString))
{
var grid = button.Content as Grid;
if (grid != null)
buttonContentString = string.Join("", grid.Children.OfType<ContentControl>().Select(x => x.Content));
}
var caret_index = LastFocusedTextBox.CaretIndex;
LastFocusedTextBox.Text = LastFocusedTextBox.Text.Insert(caret_index, buttonContentString);
LastFocusedTextBox.Focus();
LastFocusedTextBox.CaretIndex = caret_index + buttonContentString.Length;
}
}
}
Notice how the Button are passed to the method instead of being stored in a field. Also, unnecessary fields, both in the class and local to the all_in_one() method were removed. To get the contents of the labels in the Grid (e.g. "1!" - I assume this is what you were after, since nothing else could go into a simple string field, and also match the general pattern of your first two buttons), we simply select their contents and join them into a single string, after checking if the content was a string or a Grid.

"UpdateSourceTrigger=PropertyChanged" equivalent for a Windows Phone 7 TextBox

Is there a way to get a TextBox in Windows Phone 7 to update the Binding as the user types each letter rather than after losing focus?
Like the following WPF TextBox would do:
<TextBox Text="{Binding Path=TextProperty, UpdateSourceTrigger=PropertyChanged}"/>
Silverlight for WP7 does not support the syntax you've listed. Do the following instead:
<TextBox TextChanged="OnTextBoxTextChanged"
Text="{Binding MyText, Mode=TwoWay,
UpdateSourceTrigger=Explicit}" />
UpdateSourceTrigger = Explicit is a smart bonus here. What is it? Explicit: Updates the binding source only when you call the UpdateSource method. It saves you one extra binding set when the user leaves the TextBox.
In C#:
private void OnTextBoxTextChanged( object sender, TextChangedEventArgs e )
{
TextBox textBox = sender as TextBox;
// Update the binding source
BindingExpression bindingExpr = textBox.GetBindingExpression( TextBox.TextProperty );
bindingExpr.UpdateSource();
}
I like using an attached property. Just in case you're into those little buggers.
<toolkit:DataField Label="Name">
<TextBox Text="{Binding Product.Name, Mode=TwoWay}" c:BindingUtility.UpdateSourceOnChange="True"/>
</toolkit:DataField>
And then the backing code.
public class BindingUtility
{
public static bool GetUpdateSourceOnChange(DependencyObject d)
{
return (bool)d.GetValue(UpdateSourceOnChangeProperty);
}
public static void SetUpdateSourceOnChange(DependencyObject d, bool value)
{
d.SetValue(UpdateSourceOnChangeProperty, value);
}
// Using a DependencyProperty as the backing store for …
public static readonly DependencyProperty
UpdateSourceOnChangeProperty =
DependencyProperty.RegisterAttached(
"UpdateSourceOnChange",
typeof(bool),
typeof(BindingUtility),
new PropertyMetadata(false, OnPropertyChanged));
private static void OnPropertyChanged (DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var textBox = d as TextBox;
if (textBox == null)
return;
if ((bool)e.NewValue)
{
textBox.TextChanged += OnTextChanged;
}
else
{
textBox.TextChanged -= OnTextChanged;
}
}
static void OnTextChanged(object s, TextChangedEventArgs e)
{
var textBox = s as TextBox;
if (textBox == null)
return;
var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
}
}
}
Not through binding syntax, no, but it's easy enough without. You have to handle the TextChanged event and call UpdateSource on the binding.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
((TextBox) sender).GetBindingExpression( TextBox.TextProperty ).UpdateSource();
}
This can be converted into an attached behavior as well pretty easily.
In TextChanged event call UpdateSource().
BindingExpression be = itemNameTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
You can write your own TextBox Behavior to handle Update on TextChanged:
This is my sample to PasswordBox but you can simple change it to handle any property of the any object.
public class UpdateSourceOnPasswordChangedBehavior
: Behavior<PasswordBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PasswordChanged += OnPasswordChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PasswordChanged -= OnPasswordChanged;
}
private void OnPasswordChanged(object sender, RoutedEventArgs e)
{
AssociatedObject.GetBindingExpression(PasswordBox.PasswordProperty).UpdateSource();
}
}
Ussage:
<PasswordBox x:Name="Password" Password="{Binding Password, Mode=TwoWay}" >
<i:Interaction.Behaviors>
<common:UpdateSourceOnPasswordChangedBehavior/>
</i:Interaction.Behaviors>
</PasswordBox>
UpdateSourceTrigger=Explicit doesnt work for me, hence Im using custom class derivated from TextBox
public class TextBoxEx : TextBox
{
public TextBoxEx()
{
TextChanged += (sender, args) =>
{
var bindingExpression = GetBindingExpression(TextProperty);
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
}
};
}
}
It's just one line of code!
(sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource();
You can create a generic TextChanged event (for example "ImmediateTextBox_TextChanged") in the code behind of your page, and than link it to any TextBox in the page.
I took Praetorian's answer and made an extension class that inherits TextBox so you don't have to muddle up your view's code behind with this behavior.
C-Sharp:
public class TextBoxUpdate : TextBox
{
public TextBoxUpdate()
{
TextChanged += OnTextBoxTextChanged;
}
private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
TextBox senderText = (TextBox)sender;
BindingExpression bindingExp = senderText.GetBindingExpression(TextBox.TextProperty);
bindingExp.UpdateSource();
}
}
VisualBasic:
Public Class TextBoxUpdate : Inherits TextBox
Private Sub OnTextBoxTextChanged(sender As Object, e As TextChangedEventArgs) Handles Me.TextChanged
Dim senderText As TextBox = DirectCast(sender, TextBox)
Dim bindingExp As BindingExpression = senderText.GetBindingExpression(TextBox.TextProperty)
bindingExp.UpdateSource()
End Sub
End Class
Then call like this in XAML:
<local:TextBoxUpdate Text="{Binding PersonName, Mode=TwoWay}"/>

Why does KeyDown event not have access to the current value of bound variable?

In the example below:
I start program, type text, click button, see text above. Press ENTER see text again.
BUT:
I start program, type text, press ENTER, see no text.
It seems that the KeyDown event doesn't get access to the current value of the bound variable, as if it is always "one behind".
What do I have to change so that when I press ENTER I have access to the value that is in the textbox so I can add it to the chat window?
alt text http://www.deviantsart.com/upload/1l20kdl.png
XAML:
<Window x:Class="TestScroll.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="290" Width="300" Background="#eee">
<StackPanel Margin="10">
<ScrollViewer Height="200" Width="260" Margin="0 0 0 10"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<TextBlock Text="{Binding TextContent}"
Background="#fff"/>
</ScrollViewer>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<TextBox x:Name="TheLineTextBox"
Text="{Binding TheLine}"
Width="205"
Margin="0 0 5 0"
KeyDown="TheLineTextBox_KeyDown"/>
<Button Content="Enter" Click="Button_Click"/>
</StackPanel>
</StackPanel>
</Window>
Code-Behind:
using System;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
namespace TestScroll
{
public partial class Window1 : Window, INotifyPropertyChanged
{
#region ViewModelProperty: TextContent
private string _textContent;
public string TextContent
{
get
{
return _textContent;
}
set
{
_textContent = value;
OnPropertyChanged("TextContent");
}
}
#endregion
#region ViewModelProperty: TheLine
private string _theLine;
public string TheLine
{
get
{
return _theLine;
}
set
{
_theLine = value;
OnPropertyChanged("TheLine");
}
}
#endregion
public Window1()
{
InitializeComponent();
DataContext = this;
TheLineTextBox.Focus();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
AddLine();
}
void AddLine()
{
TextContent += TheLine + Environment.NewLine;
}
private void TheLineTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
AddLine();
}
}
#region INotifiedProperty Block
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
Your textbox->property binding is only happening after the textbox loses focus. When you type in text and press enter, you have not set the focus anywhere else on the form. You can demonstrate this by typing in your text, clicking on the scroll viewer, then clicking back on the textbox and hitting enter. You will then see your text change in the viewer.
To get around that, update your Text property of the textbox to this.
Text="{Binding TheLine, UpdateSourceTrigger=PropertyChanged}"
http://blogs.msdn.com/wpfsdk/archive/2006/10/19/wpf-basic-data-binding-faq.aspx
See about a quarter of the way down the page: How do I make my data-bound TextBox update the source value as I type?
Does it work if you change AddLine to use TheLineTextBox.Text?
void AddLine()
{
TextContent += TheLineTextBox.Text + Environment.NewLine;
}
This way is used to WPF, on the other hand when use the silverlight the property UpdateSourceTrigger has only default and explicit value.

Categories

Resources