Mvvm wpf: update value binding before leaving focus of input element - c#

I have this element in my xaml (DevExpress item):
<dxe:ComboBoxEdit IsTextEditable="False" EditValue="{Binding IDTIPOCONN}"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window},Path=DataContext.ttc}" />
All the binding are correct, and when I change the value, I trigger some event from my ViewModel.
My problem is the update of the value is executed only when I leave the focus of my comboBox. I need, instead, to execute my action when the value is changed, before leaving its foucs.
How can I do it? I need this because selecting one or another from the list, I show to the user some hidden elements.

Try for Binding set UpdateSourceTrigger=PropertyChanged:
<dxe:ComboBoxEdit IsTextEditable="False"
EditValue="{Binding Path=IDTIPOCONN, UpdateSourceTrigger=PropertyChanged}" ... />
In this case, most likely the default value of UpdateSourceTrigger is LostFocus.

Related

How to bind different properties to SelectedItem and SelectedIValue of ComboBox?

I have a thread that updates the current Mode property every second. I also want an option to be able to set a mode within the same cell in datagrid. So, in not editing mode I just show the mode. In editing mode, I show a populated ComboBox.
Now,
to be able to show the selected item in ComboBox, when I enter the editing mode, I bind the SelectedItem to Mode.
to be able to get the changes back to the ViewModel I bind SelectedValue to a different property. ( I need to bind to a different property since 'Mode' is updated every second and will overwrite the selected value).
The problem is that though SelectedItem is bound with Mode=OneTime it still triggers SelectedValue property. I want the SelectedValue to be triggered only when user select a value.
I hope it's clear what I'm trying to do. So, how I can achieve this? Other approaches are welcome (even if I need to use a different control).
<DataGridTemplateColumn Header="Mode">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Mode}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource Modes}}"
SelectedItem="{Binding Mode, Mode=OneTime}"
SelectedValue="{Binding ModeToSet, Mode=OneWayToSource}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
The premise of what needs to be done is not attainable due to the way the combobox works and how Mode is constantly changing in the background.
Why?
The problem is that though SelectedItem is bound with Mode=OneTime it
still triggers SelectedValue property.
As it should. OneTime as per the docs (BindingMode Enumeration) states:
"Updates the binding target when the application starts or when the data context changes."
The data context as per your design is always changing once a second. If one reads farther into the description it states
"This type of binding is appropriate if you are using data where either a snapshot of the current state is appropriate to use or the data is truly static. ... This is essentially a simpler form of OneWay binding..."
And if one reads up on OneWay bindings
"Updates the binding target (target) property when the binding source (source) changes. This type of binding is appropriate if the control being bound is implicitly read-only."
A combo box is ultimately designed to change both SelectedItem and to get the value off of SelectedItem into SelectedValue
I want the SelectedValue to be triggered only when user select a value.
The problem is not going out of the control, it is what is coming in....
Create a test project and the combobox behaves the way you specify, selected value is only triggered when a user selects a value. Comboboxes only sets the SelectedX properties when a choice is made or an outside value has changed one so it changes the other.
Since Mode is constantly changing it is pushing the change into the selection, not visa versa.
Suggestion To Fix
I suggest you take a snapshot of mode and place that into a ModeOnEdit variable and bind that. When the user makes the selection, capture the event and change the actual Mode.
Test Project
Bind to your own data source, mine was Ships. Ships is a list with and Name as a property on that object. ToString on the ship object returns Name.
Here is the result, there are two textboxes which show the state of the selected item/value. A button to set the selected value and the combobox itself.
<Label Grid.Row="1" Grid.Column="1">SelectedItem</Label>
<TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding SelectedItem, ElementName=cbMain}"/>
<Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2">SelectedValue</Label>
<TextBlock Grid.Row="3" Grid.Column="2" Text="{Binding SelectedValue, ElementName=cbMain}"/>
<Button Grid.Row="5" Grid.Column="1" Click="ChangeSelectedValue">Set Selected Value</Button>
<ComboBox Name="cbMain"
Grid.Row="5"
Grid.Column="2"
ItemsSource="{Binding Ships}"
SelectedValuePath="Name"/>
-- Code behind
private void ChangeSelectedValue(object sender, RoutedEventArgs e)
{
cbMain.SelectedValue = "Pacific Silver";
}

WPF Activate binding OnTextInput on textbox

I have a textbox with the following binding :
<TextBox Binding={Path=MyStr, Mode=TwoWay}>
My problem is that the binding only fires when the textbox loses focus and not for each char the user enters.
The textbox also has an OnTextInput function that fires properly but how do I activate the binding in the code behind?
*I'd rather doing it in a pure mvvm way (not use the window's code behind if possible)
Any answer will be accepted mvvm or not.
Here:
<TextBox Text="{Binding Path=MyStr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
now your bound property will be changed on each character.
U can use the updatesource trigger and set it to property changed
<Binding Source="{StaticResource myDataSource}" Path="Name"
UpdateSourceTrigger="PropertyChanged"/>
The moment it is changed it will sent it's updated value back to your DataContext
on msdn:
http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger.aspx
There is a UpdateSourceTrigger Called PropertyChanged, if you use that as your update trigger when you change the text of the textbox it will fire and in your binding property setter you can perform what ever action you need to happen as text changes.
<TextBox Text="{Binding Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

Remove elements from window based on Combobox selection xaml

I have the following situation: inside xaml I get values from a database and fill the combobox..if the selected item in the combobox has a value "x" I want to hide some elements from the working window..thx for your tips
<TextBlock Text="XYZ:"/>
<ComboBox ItemsSource="{Binding DataContext.KeyLists.XYZ,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
SelectedValuePath="XYZId"
SelectedValue="{Binding XYZId, Mode=TwoWay}"
DisplayMemberPath="Name" />
There are many ways to solve this.
you can make IValueConverter to convert selection values to Visibility, apply to each control with different converter parameter
you can write styles with triggers for the convtols
you could (not recommended) handle this in code

Getting Checked property from CheckBox when Command is called in WPF

I have a grid of CheckBoxes in a WPF C# project. Each CheckBox's Command property is bound to a CheckBoxChangedCommand in my WView.xaml file, like so:
<CheckBox Grid.Row="0" IsChecked="true" x:Name ="CheckBox0"
Command="{Binding CheckBoxChangedCommand}" />
<CheckBox Grid.Row="1" IsChecked="true" x:Name="CheckBox1"
Command="{Binding CheckBoxChangedCommand}" />
Each time one of the CheckBoxes is either checked or unchecked, I call CheckBoxChanged. How would I go about displaying a pop-up window showing either 1. the row number in the grid of the CheckBox and the name of the CheckBox ("CheckBox0", for example) and 2. The Checked value (true/false) for the checkbox?
My CheckBoxChangedCommand, in WViewModel.cs file, looks like this:
public ICommand CheckBoxChangedCommand
{
get
{
return new RelayCommand(param =>
{
MessageBox.Show("CheckBoxChanged!");
});
}
}
How can I access the IsChecked property and the row number of the CheckBox that triggered CheckBoxChanged from withinCheckBoxChanged? How can I pass the data from my View to my ViewModel?
You definitely need to do more with binding here.
First of all, you should probably be binding the IsChecked property of your Checkboxes to a property on your viewmodel.
Second, based on your comment about needing to know the row number of the checkbox that was checked, I'd say you probably need to be generating the "row" including the CheckBox via databinding, so that you can then pass the object that represents the row as the CommandParameter to your CheckBoxChangedCommand.
So something like:
<ListBox ItemsSource="{Binding MyItems}" />
and then in your resources:
<DataTemplate DataType="{x:Type local:MyItemType}">
<CheckBox IsChecked="{Binding IsChecked}"
Command="{Binding CheckChangedCommand}"
CommandParameter="{Binding}" />
</DataTemplate>
Note: Your CheckChangedCommand is probably on the main ViewModel, not the item-level ViewModel, so you probably need to do some other type of lookup to make it find it - this example is just for simplicity

Tabbing or Deselecting Cell not Committing Data

I am working with the the WPF Toolkit DataGrid and currently have a problem with committing data back to the source.
My grid is bound to a CLR object list and I have a converter with both the convert and convert back methods implemented.
The two way binding works fine if the user hits Enter in the cells but if they deselect or tab out of the cells the data that was typed is lost.
I have put a break on the CellEditEnding event and both events for Tab and Enter seem identical, but when it gets to the ConvertBack method on my converter the value is empty.
Any help would be much appreciated.
Try changing the UpdateSourceTrigger parameter of your control's Binding to PropertyChanged instead of the default LostFocus.
Eg
<TextBox
Width="75"
VerticalAlignment="Top"
Margin="10"
Text="{Binding
Source={StaticResource data},
Path=Age,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}"
Style="{StaticResource textBoxInError}" />

Categories

Resources