I am currently trying to prevent a user from inputting anything aside from numbers into a textbox.
I currently have a Textbox with a textchange event which calls a relay command. however I am not able to effect the textbox from the relay command.
I have tried directly settings the textbox.text and that has not worked, nor has trying to return the string.
Here is my code
XAML
<TextBox x:Name="TextBox" Margin="5,5,0,0" Grid.Column="1" Grid.Row="3" HorizontalAlignment="Left" Width="31" ">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<command:EventToCommand Command="{Binding TextBoxTextChanged,Mode=TwoWay}"
CommandParameter="{Binding Path=Text, ElementName=TextBox}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
View Model
DaysBackTextChanged = new RelayCommand<string>(daysBackText =>
{
Func<string> function = () =>
{
if (!Regex.IsMatch(daysBackText, "[^0-9]+"))
{
//return TextBox.Text;
return "X";
}
else
{
return "Y";
}
};
});
Modify your XAML to add a PreviewTextInput event in the TextBox
PreviewTextInput="NumbersOnly"
Now,let's use Regex,shall we ?
using System.Text.RegularExpressions;
private void NumbersOnly(object sender, TextCompositionEventArgs e)
{
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
Here e.Handeled is to prevent anything rather than numbers being typed.
Hope this works :)
Related
I am triggering password change event and command action
xaml
<PasswordBox VmWindow:PasswordHelper.Attach="True" Height="25" Width="180" HorizontalAlignment="Left"
FontFamily="Arial" FontSize="11" BorderBrush="#FF959BA0" TabIndex="2"
VmWindow:PasswordHelper.Password="{Binding Path=Password, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="PasswordChanged">
<i:InvokeCommandAction Command="{Binding ChangePasswordCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</PasswordBox>
Password changed event code:
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
Command Action
public ICommand ChangePasswordCommand { get; private set; }
public LoginViewModel ViewModel { get; set; }
private void ExecuteChangePasswordCommand()
{
try
{
if (loginModel != null)
{
loginModel.LoginPassword = Password;
}
}
catch (Exception exception)
{
}
}
Problem:
What is happening intially when application loads i enter char in textbox the "Event fires first and then action which ok normal senario",but when i press second char "my Action fires first then trigger that is the problem"
I don't know weather it is predefined process or am i doing something wrong .Because according to me order should always Event,action not Action,event
Please let me know where i am wrong.
Finally after spending a lot of time i am able to solve the above problem with some additional changes
Add Reference of Microsoft.Expressions.Interactions
Add two refrences:
xmlns:i="clrnamespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei=http://schemas.microsoft.com/expression/2010/interactions
Done few changes in password box:
<PasswordBox VmWindow:PasswordHelper.Attach="True" Height="25" Width="180" HorizontalAlignment="Left"
FontFamily="Arial" FontSize="11" BorderBrush="#FF959BA0" TabIndex="2"
VmWindow:PasswordHelper.Password="{Binding Path=Password, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="PasswordChanged">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="changePassword"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</PasswordBox>
Create a Method in Your LoginViewModel
public void changePassword(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
loginModel.LoginPassword = passwordBox.Password;
}
Done With changes its clean MVVM with no code behind now
I created a TextBox. I wrote a TextChanged event in view model. The problem is, when I type 'a' in the TextBox, in the TextChanged event, I am getting "". Then if I type next letter 'b', I am getting the previous result 'a' and If I type the next letter 'c', I am getting 'ab' as result. Why is one char delay in the TextChanged event?
Here is my XAML code:
<toolkit:PhoneTextBox Visibility="{Binding IsSearchBoxVisible,Converter={StaticResource BoolToVisibilityConverter}}" TextChanged="txtboxPhoneContacts_TextChanged" Grid.Row="2" Width="450" FontSize="28" Foreground="Black" x:Name="txtboxPhoneContacts" VerticalContentAlignment="Center" Background="LightGray" Hint="{Binding Localizedresources.SearchContactsText,Source={StaticResource LocalizedStrings}}" Text="{Binding PhoneContactSearchText,Mode=TwoWay,UpdateSourceTrigger=Explicit}" Style="{StaticResource SearchTextBoxStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding PhoneBookTextBoxTextChanged}" CommandParameter="{Binding Text,ElementName=txtboxPhoneContacts,BindsDirectlyToSource=True}"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<controls:UpdateOnTextChangedBehavior></controls:UpdateOnTextChangedBehavior>
</i:Interaction.Behaviors>
</toolkit:PhoneTextBox>
My ViewModel.cs
private void OnPhoneBookTextBoxTextChanged(Object obj)
{
if (obj != null)
{
String text = obj.ToString();
searchResults = new ObservableCollection<PhoneBookEntity>(
from item in PhoneContactsList
where item.PhoneContactName.Contains(text)
select item);
}
}
Any suggestions is highly appreciated.
I've been working with WPF and I have experienced a problem related with DataTemplates.
I have a view called DetailPage.xaml and this view uses a DataTemplate called Detail.xaml. I added a textbox to this DataTemplate and I want to handle the TextChanged event. So I made something like this:
<DataTemplate x:Name="DetailContent">
<Grid Margin="5" DataContext="{Binding Items[0]}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition MaxHeight="80"/>
</Grid.RowDefinitions>
<StackPanel Width="432">
<TextBox Name="NumeroParadaTB" Text="{Binding NumeroParada}" MaxLength="5" TextChanged="NumeroParadaTB_TextChanged" />
</StackPanel>
</Grid>
</DataTemplate>
Then I created and event handler in DetailPage.xaml.cs, like the following:
protected async void NumeroParadaTB_TextChanged(object sender, TextChangedEventArgs e)
{
string nroParada = ((TextBox)sender).Text;
if(!string.IsNullOrEmpty(nroParada) && nroParada.IsDigitsOnly() && nroParada.Length == 5)
{
}
}
But when running, and error is thrown saying that the event handler doesn't exist. I guess I'm using the eventhandler in a wrong way.
Thanks!
Since you're using data binding, I assume, that you have some class with NumeroParada property:
public class SomeClass : INotifyPropertyChanged
{
/* other code here */
public string NumeroParada
{
get { return numeroParada; }
set
{
if (numeroParada != value)
{
numeroParada = value;
OnPropertyChanged("NumeroParada");
}
}
}
private string numeroParada;
}
Setter of this property will fire, when UI will update the binding source. This is your "TextChanged" event.
Note, that by default, TextBox updates Text property, when loosing focus. If you want to perform any action when user changes text, update your binding definition:
Text="{Binding NumeroParada, UpdateSourceTrigger=PropertyChanged}"
So far so good. But this code:
if(!string.IsNullOrEmpty(nroParada) && nroParada.IsDigitsOnly() && nroParada.Length == 5)
suggests, that you're trying to implement validation of value, entered by user.
Validation in WPF is rather big theme, I'd recommend you to read something like this to select validation approach.
Instead of adding an Event handler, you can use Event to Command logic. Create a Command in ViewModel and bind it to the TextChanged event.
<TextBox Text="{Binding SearchText, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding MyCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
Interaction triggers available in System.Windows.Interactivity assembly.
I'm doing WPF MVVM and have the following XAML code:
<TextBox Grid.Row="1" Name="Console" MinWidth="500" HorizontalAlignment="Stretch" AcceptsReturn="True" CharacterCasing="Upper" TextWrapping="WrapWithOverflow" Cursor="IBeam">
<TextBox.InputBindings>
<KeyBinding Command="{Binding Path=MyCommand}" CommandParameter="{Binding Text, ElementName=Console}" Key="Enter"/>
</TextBox.InputBindings>
</TextBox>
When handling the Enter press in the ViewModel's command property (initialized in constructor with event handler added):
private readonly MyCommand myCommand;
public ICommand MyCommand
{
get
{
return myCommand;
}
}
private void OnCommand(object sender, MyCommandEventArgs e)
{
<do something>
}
The event handler is called allright, but the Enter keypress is never passed back to the TextBox and the newline is not added (the cursor stays on the same line).
Doesn't event bubbling ensure that the Enter keypress gets passed on to the TextBox?
Could you just add "\n" to your textbox' Text-value?
(Would have add that as a comment but I may not do that yet...)
I defined an ICommand-Class ReadPersons which reads all person objects from the database with a particular where-clause.
The command is being executed trough pressing a button and the where-clause is being insert in a textbox.
Question: How can i pass the text from the textbox to the Execute-Command?
MainWindow.xaml:
<Button Command="{Binding ReadPersons}">Read persons</Button>
<TextBox Name="textBoxWhereClause" />
ReadPersons.cs:
public void Execute(object parameter)
{
// Read all persons with my where-clause
string whereClause = ??? //todo
}
Yes you can.
<Button Command="{Binding ReadPersons}"
CommandParameter="{Binding Text, ElementName=textBoxWhereClause}">
Read persons</Button>
<Button Command="{Binding ReadPersons}" CommandParameter="{Binding SomeProperty}" Content="Read Persons"/>