INotifyPropertyChanged update ontextchange - c#

I have the following binding in my wpf application
xaml:
<TextBox Text="{Binding Amount, StringFormat=c}" Name="txtAmount" />
c# (code behind):
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
// needed to create the binding
this.DataContext = this;
}
private decimal _Amount;
public decimal Amount
{
get {
return _Amount;
}
set{
_Amount= value;
OnPropertyChanged("Amount");
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
//.....
that code works fine. The property Amount in my code behind will be updated whenever I change the value of txtAmount and also the other way around (changing the value of Amount in C# will update txtAmount)
Anyways how can I update amount every time I change the text in the control txtAmount? I don't want to wait until txtAmount loses focus so that Amount get's updated in the code behind.
Things I have tried:
txtAmount.TextChanged += (a, b) =>
{
Amount = decimal.Parse(txtAmount.Text);
};
Recall that my txtAmount is formatted as currency therefore if it has the value of 1 the txtAmount will display $1.00 I know that I should be able to replace the $ for nothing in order to be able to cast it to decimal. If this application where to use a different culture say for instance es for Spanish then the textbox will display a eruo instead of the $ and I will have to replace that symbol in order to be able to cast it.
So in short is there a way of being able to update the Amount property that is binded to my txtAmount control everytime the text changes in that control instead of when the control looses focus?

Set the binding property UpdateSourceTrigger to PropertyChanged
<TextBox Text="{Binding Amount, StringFormat=c, UpdateSourceTrigger=PropertyChanged}" Name="txtAmount" />

So in short is there a way of being able to update the Amount property that is binded to my txtAmount control everytime the text changes in that control instead of when the control looses focus?
In short:
<TextBox Text="{Binding Amount, StringFormat=c,
UpdateSourceTrigger=PropertyChanged}" Name="txtAmount" />

Related

C# WPF MVVM Textbox Clearing without breaking Command Bindings?

googling for this showed me that this is often a problem but never reallay solved.
I do have an App/Prgramm in C#, i'll try to be mvvm conform.
I do have an window, in it a UserControl show different views.
One of my view contains a textbox, the text of the textbox is bound to a proptery of the VM.
My textbox got 2 inputbindings, for "enter" and "return" - both leading to same command.
On hitting "enter" the value of the textbox should be processed, the textbox shoud be cleared and refocused ... This works .... One Time ....
Clearing the textbox with String.Empty breaks the Bindings ... this could be found in several postings here ... the most Solution is textboxname.clear() ...
But i dont have the "textboxname" in the viewmodel, only in code-behind, but all my logic is in the VM ... So can somebody pls help me sort things out, how i could clear the textbox without breaking the bindings to input text and hit enter more then one time ?
My Code
<TextBox x:Name="tb_checkinbox" Grid.Row="0" Grid.Column="1" Width="200" Height="25" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding CheckInNumber}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding OnCheckInEnterCommand}" Key="Return"/>
<KeyBinding Command="{Binding OnCheckInEnterCommand}" Key="Enter"/>
</TextBox.InputBindings>
</TextBox>
public CheckinVM()
{
OnCheckInEnterCommand = new RelayCommand(OnCheckInEnter, CanCheckInEnter);
}
private string _checkInNumber;
public string CheckInNumber
{
get { return _checkInNumber; }
set { SetProperty(ref _checkInNumber, value); }
}
public ICommand OnCheckInEnterCommand { get; set; }
public void OnCheckInEnter(object value)
{
CheckInNumber = String.Empty;
/// More to do
}
public bool CanCheckInEnter(object value)
{
return true;
}
The assignment
CheckInNumber = string.Empty;
does not "clear" any Binding. Your conclusion is wrong.
You do however only get empty strings - after clearing - in the setter of the CheckInNumber property. In order to get property updates not only when the TextBox loses focus or you reset the source property, set UpdateSourceTrigger=PropertyChanged on the Text Binding:
<TextBox ... Text="{Binding CheckInNumber, UpdateSourceTrigger=PropertyChanged}">

C# visible doesn't works

I'm making a Universal application for Windows Phone 8.1 and have a problem with my code.
After TextBlock value become greater or equal than 22, some images should become visible. If the value is less than 22 all images should be invisible.
My question: How I can get visible images after textblock value >="22"
This is my code to hide images:
private void points_Loaded(object sender, RoutedEventArgs e)
{
int n = 0;
bool b = int.TryParse(points.Text, out n);
DataContext = this;
ImageVis = (b && n >= 22) ? Visibility.Visible : isibility.Collapsed;
}
private Visibility imageVis;
public Visibility ImageVis
{
get { return imageVis; }
set
{
imageVis = value;
RaisePropertyChanged("ImageVis");
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void RaisePropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
This code part is from XAML:
<Image x:Name="hole17img"
HorizontalAlignment="Left"
Height="57"
Margin="10,3540,0,0"
VerticalAlignment="Top"
Width="380"
Source="Assets/septinpatsmit.png"
Stretch="Fill"
Visibility="{Binding ImageVis, Mode=TwoWay}"/>
I have problem with: RaisePropertyChanged("ImageVis");
The name 'RaisePropertyChanged' does not exist in the current context
Does this mean I have make some object with that name? or something else?
I can provide my My application so you can see what's happening.
My application sample
RaisePropertyChanged is MVVM Light's method and makes UI updated whenever you raise a property with the given name.In the XAML code behind , you bind ViewModel's properties to XAML properties and when RaisePropertyChanged triggers , it notifies the given property and UI is refreshed after.
You also need to use Converters to convert boolean to Visibility.In general , you need more MVVM Pattern knowledge to Windows projects.
Check out this post
http://www.mvvmlight.net/doc/

How to see if RichTextBox value appeared on the UI

I have a LongListSelector and use inside it a RichTextBox
<DataTemplate>
<Grid>
<RichTextBox>
<Paragraph>
<Run Text="{Binding Description}"/>
</Paragraph>
</RichTextBox>
</Grid>
</DataTemplate>
because of a long list of data, there is a delay in appearing RichTextBox's data. everything is loaded but texts appear later.
No problem with a delay, but It gets annoying when I try to scroll to a particular item in LongListSelector by its .ScrollTo method. In the Loaded event handler of the form or the LLS (no difference) I call ScrollTo but its execution finishes and scrolls to the item before appearing the text of RichTextBox on the screen, So after appearing the text, it gets longer, and it is not on the right item any more.
I thought of a delay in executing the ScrollTo method, to let everything appear in the screen, but since my app is not multithread, I couldn't end up with a successful sleep or timer.
How can I solve this? How can I wait until RichTextBox's loading finished?
(It's a WP8 app)
You could try using LayoutUpdated(), the last time it fires the content is loaded.
Try to implement Property Change Notification
public class YourClass: INotifyPropertyChanged
{
private string description;
public event PropertyChangedEventHandler PropertyChanged;
public string Description
{
get { return description; }
set
{
description= value;
OnPropertyChanged("Description");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
And when you set Description = "blablabla" it will notify your RichTextBox.
Hope it's help

How to set SelectedId of Combobox and set text of Textbox in a specific format from ViewModel in WPF

I am working on a textbox and combobox in my wpf app. I am sorry for weird title. Well here is the scenario:
Xaml:
<ComboBox ItemsSource="{Binding PortModeList}" SelectedItem="{Binding SelectedPortModeList, Mode=OneWayToSource}" SelectedIndex="0" Name="PortModeCombo" />
<TextBox Grid.Column="1" Text="{Binding OversampleRateBox}" Name="HBFilterOversampleBox" />
ViewModel Class:
public ObservableCollection<string> PortModeList
{
get { return _PortModeList; }
set
{
_PortModeList = value;
OnPropertyChanged("PortModeList");
}
}
private string _selectedPortModeList;
public string SelectedPortModeList
{
get { return _selectedPortModeList; }
set
{
_selectedPortModeList = value;
OnPropertyChanged("SelectedPortModeList");
}
}
private string _OversampleRateBox;
public string OversampleRateBox
{
get
{
return _OversampleRateBox;
}
set
{
_OversampleRateBox = value;
OnPropertyChanged("OversampleRateBox");
}
}
Here I have three requirements:
By using SelectedIdin xaml I am able to select the id but I want to set the selectedid of my combobox from viewmodel class. I.e.
int portorder = 2
PortModeList->SetSelectedId(portOrder). How can I do something like this? or is their any other approach?
I need to restrict number of entries inside a textbox to 4. I.e. 1234 is entered in textbox, it should not let user exceed 4 digits.
I want to set the format of text in OversampleRateBox as: 0x__. I.e. if user wants to enter 23 present in a variable, then I shud set text as 0x23. Basically 0x should be present at the beginning.
Please help :)
I would use the SelectedItem property of the ComboBox (as you are doing), but make the binding two-way. Then, you can set your SelectedPortModeList (which should be called SelectedPortMode) in your view model.
<ComboBox ItemsSource="{Binding PortModeList}"
SelectedItem="{Binding SelectedPortMode}" ...
In the view model:
// Select first port mode
this.SelectedPortMode = this.PortModeList[0];
If you want to limit the number of characters in a TextBox, then use the MaxLength property:
<TextBox MaxLength="4" ... />
If you wish to add a prefix to the OversampleRateBox, one option would be to test for the presence of this in the setter for OversampleRateBox, and if it's not there, then add it before assigning to your private field.
Update
Bind your TextBox to a string property:
<TextBox Grid.Column="1" Text="{Binding OversampleRateBox}" ... />
In the setter for your property, check that the input is valid before setting your private field:
public string OversampleRateBox
{
get
{
return _OversampleRateBox;
}
set
{
// You could use more sophisticated validation here, for example a regular expression
if (value.StartsWith("0x"))
{
_OversampleRateBox = value;
}
// Now if the value entered is not valid, then the text box will be refreshed with the old (valid) value
OnPropertyChanged("OversampleRateBox");
}
}
Because the binding is two-way, you can also set the value from your view model code (for example in the view model constructor):
this.OversampleRateBox = "0x1F";

It doesnt change property,which is binded(mode TwoWay)

I have text box,i binded its Text property to MainTxtBoxTxt property in ModalView of Window.When MainTxtBoxTxt changes it affects to TextBox,but when Text property of TextBox changes it doesnt affect to MainTxtBoxTxt in ModelView.What is the problem?
<cstmTxtBox:CustomTextBox Grid.Row="0" TextWrapping="Wrap" FontSize="16" x:Name="TxtBox" cstmTxtBox:CustomTextBox.CaretIndex="{Binding Path=CaretIndex, Mode=TwoWay}" Text="{Binding Path=MainTxtBoxText,Mode=TwoWay}" >
CustomTxtBox
public class CustomTextBox : TextBox
{
public CustomTextBox()
{
}
public static DependencyProperty CaretIndexProperty =DependencyProperty.RegisterAttached( "CaretIndex",typeof(int),typeof(CustomTextBox),new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetCaretIndex(UIElement element, int value)
{
element.SetValue(CaretIndexProperty, value);
}
public static int GetCaretIndex(UIElement element)
{
return (int)element.GetValue(CaretIndexProperty);
}
}
Try this
Text="{Binding Path=MainTxtBoxText,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Use following:
<cstmTxtBox:CustomTextBox Grid.Row="0" TextWrapping="Wrap" FontSize="16" x:Name="TxtBox" cstmTxtBox:CustomTextBox.CaretIndex="{Binding Path=CaretIndex, Mode=TwoWay}" Text="{Binding Path=MainTxtBoxText,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
By default text box update view model on focus lost. Specifying UpdateSourceTrigger=PropertyChanged will update view model every time text in text box changes.
You were missing UpdateSourceTrigger property in your code which specifies how the change to data should reflect in the model property. To elaborate, UpdateSoruceTrigger property has four options to select from :-
Default - which returns the default UpdateSourceTrigger value of the target dependency property. It varies with control.
LostFocus - Changes reflect when focus move away from the current control.
PropertyChanged - reflect changes as soon as data changes. For a textbox, whenever a key is pressed, the changes occur.
Explicit - As the name suggests, it occurs on your command. you must call the UpdateSource method or the changes will not propagate back to the source

Categories