Textbox strange behavior when entering space - c#

I am using Silverlight 5 and C#. My model (CustomerModel) implements INotifyDataErrorInfo interface to validate user input. The TextBox whose Text property is bound to a Property in the model, which is being validated on every keystroke (I have set UpdateSourceTrigge=PropertyChanged), is behaving strangely - When I enter space the cursor moves to the beginning of the TextBox. Very annoying.
<TextBox x:Name="txtDebtorName" Grid.Row="2" Grid.Column="1"
Text="{Binding SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True, NotifyOnValidationError=True}"
IsReadOnly="{Binding IsReadonly}" >
</TextBox>
Any Idea what is causing this behavior, and how to fix it?
The property in the model:
public string Name
{
get { return _Name; }
set
{
const string propertyName = "Name";
ValidateRequiredString(propertyName, value, Utility.GetTranslation("RequiredFieldDebtorName"));
_Name = value;
RaisePropertyChanged(propertyName);
}
}
The ValidateRequiredString() method takes the PropertyName, the value being set and an error Message.

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}">

show/hide control textbox based on combobox selected WPF

I have a WPF/MVVM project in C #/FrameWork 4.0
In my view I have two ControlBox "NoRSAC" and "LieuRSAC"
<View:StateControlTextBox
x:Name="NoRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Text="{Binding UserVM.No_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch" />
<View:StateControlTextBox
x:Name="LieuRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Text="{Binding UserVM.Lieu_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch"/>
</Canvas>
And ControlComboBox "cmbFonction"
<View:StateControlComboBox
x:Name="cmbFonction"
ReadOnlyControlState="Disabled"
IsReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
ItemsSource="{Binding ListeFonctions}"
SelectedValue="{Binding UserVM.Fonction, Mode=TwoWay}" Width="303" Margin="0" HorizontalAlignment="Left" Canvas.Left="97" Canvas.Top="108" />
I want to view the ControlBox "NoRSAC" and "LieuRSAC" when I select a particular valeure in the ComboBox "cmbFonction" and hide when it's another selected value
Thank you for your help
In the set method of the property Fonction, you can check the value and update another property that you should introduce in your view model and that is of type System.Windows.Visibility. In the following example, I call this property TextBoxVisibility:
public class UserVM : INotifyPropertyChanged
{
private Visibility _textBoxVisibility;
public Visibility TextBoxVisibility
{
get { return _textBoxVisibility; }
set
{
_textBoxVisibility = value;
OnPropertyChanged();
}
}
public string Fonction
{
get { return _fonction; }
set
{
_fonction = value;
OnPropertyChanged();
if (value == "Value A")
TextBoxVisibility = Visibility.Hidden;
else
TextBoxVisibility = Visibility.Visible;
}
}
// Other members omitted for sake of simplicity.
}
Please note that you need to implement INotifyPropertyChanged (directly or indirectly) so that the changes of the property values are forwarded to the bindings that can in turn update the dependency properties of the controls in your view.
Thus you must not forget to add an additional binding to all of your text boxes in your view. Here is an example for that, the important part is the binding on Visibility:
<View:StateControlTextBox
x:Name="NoRSAC"
ReadOnly="{Binding IsReadOnly}"
ViewModelDataType="UtilisateurSaisieViewModel"
TableDataType="TUtilisateurDataTable"
Tag="{DynamicResource TELEPHONE}"
Visibility="{Binding UserVM.TextBoxVisibility}"
Text="{Binding UserVM.No_RSAC, Mode=TwoWay}" Margin="0" Canvas.Top="140" Width="185" VerticalAlignment="Stretch" />

Bind IsEnabled property to Boolean in WPF

I have a TextBox which needs to be enabled / disabled programmatically. I want to achieve this using a binding to a Boolean. Here is the TextBox XAML:
<TextBox Height="424" HorizontalAlignment="Left"
Margin="179,57,0,0" Name="textBox2"
VerticalAlignment="Top" Width="777"
TextWrapping="WrapWithOverflow"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
AcceptsReturn="True" AcceptsTab="True"
Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=TextBoxEnabled}"/>
Notice the Text property is bound as well; it is fully functional, which makes me think it is not a DataContext issue.
However, when I call this code:
private Boolean _textbox_enabled;
public Boolean Textbox_Enabled
{
get { return _textbox_enabled; }
set
{
OnPropertyChanged("TextBoxEnabled");
}
}
It does not work. To give further information, the TextBox_Enabled property is changed by this method:
public void DisabledTextBox()
{
this.Textbox_Enabled = false;
}
..which is called when a key combination is pressed.
Here are your little typos!
private Boolean _textbox_enabled;
public Boolean TextboxEnabled // here, underscore typo
{
get { return _textbox_enabled; }
set
{
_textbox_enabled = value; // You miss this line, could be ok to do an equality check here to. :)
OnPropertyChanged("TextboxEnabled"); //
}
}
Another thing for your xaml to update the text to the vm/datacontext
Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding TextBoxEnabled}"/>

Update datasource from control

I'm a bit new to the idea of bindings in C#. I currently have an application using MVVM that I'm working on. Say I have, for example, a list like so:
List<string> Items = new List<string>()
{
"Item1",
"Item2",
"Item3",
}
Bound to this list are three textboxes like so:
In the XAML:
<TextBox Name="TextBox1" text="{Binding TextSource1 Mode=TwoWay}">
<TextBox Name="TextBox2" text="{Binding TextSource2 Mode=TwoWay}">
<TextBox Name="TextBox3" text="{Binding TextSource3 Mpde=TwoWay}">
And in the code:
Public string TextSource1
{
get { return Items[0]; }
set { Items[0] = value; }
}
Public string TextSource2
{
get { return Items[1]; }
set { Items[1] = value; }
}
Public string TextSource3
{
get { return Items[2]; }
set { Items[2] = value; }
}
Say the displayed value in the first textbox is currently "Item1" as it is in the list. From here the user changes it to "Item4". How would I update the list from that? Does it update automatically if it's set to TwoWay?
I know in the code if I were to change a value in the list, say:
Items[2] = "Item4";
I can update the textbox by calling
RaisePropertyChanged("TextSource3");
But that's not of much help to me at the moment.
There are a couple of things to note. First when by default, a TextBox won't propagate the text changes until it loses focus. This can happen if you tab out of the control, or click on another control that can receive focus (like the other TextBoxes).
You can change this behavior by setting the UpdateSourceTrigger on the Binding (you also don't need Mode=TwoWay on a TextBox as it is the default mode):
<TextBox Name="TextBox1" text="{Binding TextSource1, UpdateSourceTrigger=PropertyChanged}" />
The second is that your properties need to raise the PropertyChanged event in their setter. While this isn't strictly necessary for a single Binding to work, you will want to do it in case you decide to have other controls bound to the same property.
Change type of Items to ObserableCollection<String>
Change binding of textbox to:
<TextBox Name="TextBox1" text="{Binding Items[0], Mode=TwoWay}">
<TextBox Name="TextBox2" text="{Binding Items[1], Mode=TwoWay}">
<TextBox Name="TextBox3" text="{Binding Items[2], Mpde=TwoWay}">
Because of ObservableCollection's internal notification mechanism, when you modify one of its element, it will notify UI.
Say the displayed value in the first textbox is currently "Item1" as it is in the list. From here the user changes it to "Item4". How would I update the list from that? Does it update automatically if it's set to TwoWay?
Yes it updates automatically when it loss focus.

IDataErrorInfo error message triggers, but no message is shown

Hello fellow programmers. I have this strange issue on Silverlight MVVM pattern using IDataErrorInfo. It's my first question made here in StackOverflow, so I hope I manage to explain it correctly. Here's the deal:
I Have this huge Job Register ChildWindow that has some controls that should only be enabled if a checkbox called HasPrevision is checked. The idea is: if the job has a Prevision, then all the controls related to the prevision are Enabled, otherwise, they are Disabled.
Now, if there is a prevision, the user MUST choose a Prevision Type in the PrevisionType ComboBox. So, if the HasPrevision checkbox is CHECKED, the PrevisionType must be selected, but if the HasPrevision checkbox is NOT CHECKED, the PrevisionType comboBox can be left unselected.
Here are the XAML for those controls (I won't show all the xaml here because it's rather big, but I believe that the problem can be solved just by showing those lines):
<!-- The HasPrevision CheckBox -->
<CheckBox Grid.Column="1"
Grid.Row="3"
x:Name="cbxHasPrevision"
IsChecked="{Binding SelectedJob.HasPrevision, Mode=TwoWay}"
Margin="0,20,2,0" />
<!-- The PrevisionType ComboBox -->
<telerik:RadComboBox Grid.Column="1"
Grid.Row="4"
x:Name="cmbPrevisionType"
IsEnabled="{Binding HasPrevision, Converter={StaticResource ControlesCadastroProcessoConverter}, ConverterParameter=IsEnabled}"
ItemsSource="{Binding PrevisionTypeList, Mode=OneWay}"
SelectedItem="{Binding SelectedJob.PrevisionType , Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, ValidatesOnNotifyDataErrors=True}"
Margin="0,4,48,4"
Height="22"
DisplayMemberPath="DsPrevisionType"/>
So, as you can see, the HasPrevision and the PrevisionType properties are binded to a property in my ViewModel called SelectedJob. SelectedJob is a Job object. All I want to do is use the IDataErrorInfo interface in my Job Class to identify if the PrevisionType is selected. Now, I can only require a PrevisionType if the HasPrevision property is "true", so my job class has this code for the IDataErrorInfo:
public string this[string columnName]
{
get
{
switch (columnName)
{
case "PrevisionType":
if (HasPrevision && (PrevisionType== null))
return "Select a PrevisionType";
break;
}
return null;
}
}
This sounds very logical to me. When I debug the code, it actually works: the switch identifies the columnName, it enters the case "PrevisionType" and it actually runs the return code inside the If statement returning the error message, not the default "return null" clause. But the error message don't show the error! Even worse: the combo box wont event validate automatically.
When the "Save" button is clicked, I check for errors and set the PrevisionType comboBox to the InvalidFocused state. The comboBox DOES get the red border around it indicating that it is in an error state, but the error message is blank. When I hover my mouse of the control, an empty small red box appears, with nothing on it.
Even more weird than that: if I REMOVE the "HasPrevision" check from the IF statement, leaving the code as follow, the message is shown and the control is validated automatically!!!
public string this[string columnName]
{
get
{
switch (columnName)
{
case "PrevisionType":
if (PrevisionType== null)
return "Select a PrevisionType";
break;
}
return null;
}
}
Everything I can think of is that since I'm trying to validate a property based on another property value, somewhere in the middle of the set's and get's the Silverlight environment gets "confused"? I don't know, I've been trying to find a solution for this for 2 days with no success.
Here are some of the other codes that I believe that are relevant.
The properties in my Job Class:
private bool _HasPrevision;
[DataMember]
public bool HasPrevision
{
get { return _HasPrevision; }
set
{
_HasPrevision= value;
RaisePropertyChanged("HasPrevision");
}
}
private PrevisionType.PrevisionType _PrevisionType { get; set; }
[DataMember]
public PrevisionType.PrevisionType PrevisionType
{
get { return _PrevisionType; }
set
{
_PrevisionType = value;
RaisePropertyChanged("PrevisionType");
}
}
My SelectedJob property in my ViewModel is:
public const string SelectedJobPropertyName = "SelectedJob";
private Objects.Register.Job.Job _SelectedJob = null;
public Objects.Register.Job.Job SelectedJob
{
get
{
return _SelectedJob;
}
set
{
if (_SelectedJob == value)
return;
var oldValue = _SelectedJob;
_SelectedJob = value;
RaisePropertyChanged(SelectedJobPropertyName , oldValue, value, true);
}
}
And my code for the Save Button is:
[...]
if(SelectedJob["PrevisionType"] != null)
{
VisualStateManager.GoToState(cmbPrevisionTypeControl, "InvalidFocused", true);
return;
}
[...]
Thanks in advance and I'm sorry if I got a little bit confused on explaining this.
EDIT 1: I had already read on those questions here, but they don't quite help me:
IDataErrorInfo - not seeing any error message even though one gets picked up
Silverlight IDataErrorInfo message does not show in custom control's textbox
I'm using the Telerik RadComboBox in similar fashion and I have no issues getting the error message displayed. Here's my XAML for your reference, hope this helps...
<TextBlock Text="Select a User to Assign the Current Step To:" Grid.Row="3" Visibility="{Binding ShowAssigneeUser}"/>
<telerik:RadComboBox x:Name="cmbAllActiveCrmUsers"
IsEditable="True"
Grid.Row="4"
telerik:TextSearch.TextPath="FullName"
Text="{Binding FullName, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
VerticalAlignment="Center"
Visibility="{Binding ShowAssigneeUser}"
ItemsSource="{Binding AllActiveCrmUsersExceptCurrentUser}"
SelectedIndex="{Binding DefaultAssigneeUserIndex, Mode=TwoWay}"
ItemTemplate="{StaticResource ComboBoxMultilineTemplate}"
Style="{StaticResource ComboBoxStyle}"
Command="{Binding AssignUserChangeCommand}"
CommandParameter="{Binding SelectedIndex, ElementName=cmbAllActiveCrmUsers}"
>
<telerik:RadComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</telerik:RadComboBox.ItemsPanel>
</telerik:RadComboBox>

Categories