I have a textblock that when the user is selected from a drop down the following TextBlock displays the "Name" of the user. This works great!
<TextBlock Text="{Binding Name, Mode=OneWay}"/>
However, on another part of the screen I a TextBox:
<TextBox x:Name="newName" Text="{Binding Name}">
Which is editable and contains the same data.
So right now when a User is selected both elements gets populated but I want to prevent the TextBlock from being updated when the TextBox is updated.
You could use "OneTime" binding mode on the textblock to get a snapshot of the data on init or context change.
-m
Related
I have TextBox that I'm using to add (only to add and not read) file path into DB. Text property is set when user selects certain file (OpenFileDialog). So, I set it in readonly state and it won't bind properly. When I remove readonly it works fine.
<Button Name="btnAddFile" Content="+" HorizontalAlignment="Left" Width="23" Height="23" Click="AddFilePath"/>
<TextBox Name="tbxFilePath" Height="23" Text="{Binding FilePath}" Width="364" IsReadOnly="True"/>
When I use:
Text="{Binding FilePath, Mode=OneWayToSource}"
it sometimes work but most of the time it doesn't (?!). I could use TextBlock or Label but I would really like to understand what is going on and use TextBox.
I'm using Entity Framework but don't think it does matter.
Question: How can I programmatically add text to TextBox control which is readonly and be able to bind it.
EDIT: I figured out what the problem is. When I set focus on TextBox after I set it's Text property from code-behind, it works. I guess it has to notify that Text is changed when I do it from code-behind. How to do that?
Have you tried using OneWay Binding?
MSDN reads:
OneWay 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.
Which I think covers your scenario.
The target is your TextBox Text property and your source is your FilePath property on your ViewModel.
Use:
Text="{Binding FilePath, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
EDIT
This answer assumes you have implemented INotifyPropertyChanged on your ViewModel.
EDIT
The correct binding mode is OneWayToSource. Confirmed by OP.
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";
}
I have an editable combobox that also has an item source which is effectively used to prompt users with some standard entries for that box whilst giving them the freedom to enter custom entries if they wish. So, everything works fine accept when I bind to a property with a value (which is not one off the list) it sets the comboboxes text to the first item in the item source. Just to be clear, the following steps demonstrate the issue.
I open the View with a clean Model (all the properties are null/default values
I enter a custom value into the editable combobox
I save the Model
I close the View
I re-open the View with the previously saved Model
The custom value which I saved should be displayed in the editable combobox, however it is overwritten by the first value in the item source list
Note: The value in the Model property is not changed, this issue is purely visual.
So, how can I stop the itemsource overwriting custom entries?
Here is the combo box XAML:
<ComboBox IsEditable="True" ItemsSource="{Binding Contact_Types, Mode=OneTime, Source={StaticResource Resources}}" Text="{Binding Model.type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
I have a window control in which I am loading a wpf user control. The wpf user control contains a combo box which is bound to a property in the view model. When I am debugging the code selected value property always has a value. When the control is loaded for the first time I am getting the selected value, but when I reload the control the combo box gets cleared. I tried everything; updating the source and other stuff, but it's still not working. I even set the datacontext in code behind, but am still not getting the expected output.
This is the XAML code:
<ComboBox x:Name="cmbType" Style="{StaticResource ComboBoxStyle}"
PreviewTextInput="cmbErrorType_PreviewTextInput" IsEditable="True"
MaxDropDownHeight="100" ItemsSource="{Binding Path=TypeList,Mode=OneWay}"
SelectedValue="{Binding Path=SelectedValue}" DisplayMemberPath="Id"
SelectedValuePath="Id" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"/>
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}" />