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

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

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

IsEnabled on Usercontrol

I'm working on my first usercontrol ang got stuck on following problem
Changing the Value of binded property doesn’t even call the property getter (a textbox does)
What is the reason for this behavior?
<luc:IpTextBox x:Name="IpTxtBxIpv4Address"
Grid.Row="1" Grid.Column="1"
IsEnabled="{Binding VmNicData.EnableIpSetting}"
Mode="IPv4Address"/>
<TextBox x:Name="TxtBxTest"
Grid.Row="1" Grid.Column="2"
IsEnabled="{Binding VmNicData.EnableIpSetting}"
Text="{Binding VmNicData.IpV4SubnetMask}"/>
ViewModel:
private bool _ipEnabled;
public bool IpEnabled
{
get => _ipEnabled;
set
{
_ipEnabled = value;
OnPropertyChanged(nameof(IpEnabled));
OnPropertyChanged(nameof(EnableIpSetting));
}
}
private bool _dhcpEnabled;
public bool DhcpEnabled
{
get => _dhcpEnabled;
set
{
_dhcpEnabled = value;
OnPropertyChanged(nameof(DhcpEnabled));
OnPropertyChanged(nameof(EnableIpSetting));
}
}
public bool EnableIpSetting => _ipEnabled && !_dhcpEnabled;
Thank's in advance
What I've done so far:
My user control contains just some textboxes. I’ve got that DataContext = this; right after initializing my usercontroll.
Setting the IsEnabled static to true or false has the expected effect on these texboxes.
As soon as I try to bind it to the property it doesn’t work at all (even if Property is false at start texboxes aren’t disabled).
I set a breakpoint at the property which doesn’t hit.
I added this txtBxTest. To see if Binding works there. It does, breackpoint was hit.
Solved: My mistake was to change the datacontext (DataContext = this in the constructor of my usercontrol). That broke my binding to parent.
Anyway thank you all for supporting
You're binded to the "EnableIpSetting", but you are not calling OnPropertyChanged when it is updated.
You need to add your OnPropertyChanged logic to the EnableIpSetting as well.

ComboBox selected item binding not showing the initial value - then working OK

I have a weird problem with something simple I suppose.
I have a combobox with two bindings set up - one for ItemsSource and another for SelectedItem.
The selected item is not working on initial startup, but then it works OK. Output does not indicate any binding problems, I have also set up a TextBlock with the same binding to see if it works - and it does.
Here's the code
<ComboBox IsSynchronizedWithCurrentItem="True" IsEditable="False"
Name="ProgramsCollectionComboBox"
SelectedItem="{Binding ElementName=ThisUc,
Path=SelectedProgram}"
ItemsSource="{Binding ElementName=ThisUc,
Path=ProgramsCollection}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="{Binding ElementName=ThisUc,
Path=SelectedProgram.Name, Mode=TwoWay}" />
The property:
private Program _selectedProgram;
public Program SelectedProgram
{
get
{
if (_selectedProgram == null)
{
_selectedProgram = new Program(Settings.Default.SelectedProgramPath);
}
return _selectedProgram;
}
set
{
_selectedProgram = value;
Settings.Default.SelectedProgramPath = SelectedProgram.PathProgramFolder;
RaisePropertyChanged("SelectedProgram");
}
}
It saves and reads the settings OK, the initial values is shown in the textblock below the combobox, when I change the selected item, the textblock is updated, the settings are changed and everything works fine - except for the fact that on app startup, selected item is not selected.
Thanks for help!
There are two reasons your initial binding is not working. First, as Jehof has mentioned himself, is the fact that you're setting your SelectedProgram to an item that is not part of the ProgramsCollection.
Furthermore, when you are setting the initial value of your SelectedProgram you are doing so in the getter, where PropertyChanged is not invoked and thus the binding will never be aware of that change. You can either invoke PropertyChanged when initializing it in the getter:
...
get
{
if (_selectedProgram == null)
{
_selectedProgram = _programsCollection?.FirstOrDefault();
RaisePropertyChanged("SelectedProgram");
}
return _selectedProgram;
}
...
Or even better, set the default value on the private field:
private Program _selectedProgram = _programsCollection?.FirstOrDefault();
...
The getter of your property SelectedProgram should return a value of your ProgrammsCollection and not a new instance if it is null.
If the value is not part of the collection that is bound to the combobox it is not displayed.

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