I have a View that contains a Combobox. The Combobox SelectedItem property is data bound to SelectedX property of View Model as two way data binding. When the viewModel is initialized, the SelectedX property is set correctly. But after that when the view renders, it resets the value of SelectedX(since the binding is two-way).
So the two way data binding for the Combobox is basically not working. Please advise.
This is the xaml for my view. I initialize the View model first with apprpriate values for Relationships and SelectedX. When the view renders, the combo box resets the value for SelectedX. (I figured that by adding breakpoints). Hope this helps
<ComboBox Grid.Row="1" Grid.Column="1" Margin="5" Background="White" BorderBrush="DarkGray"
SelectedItem="{Binding SelectedX, Mode=TwoWay}"
ItemsSource="{Binding Relationships}" DisplayMemberPath="Value"
SelectedValuePath="Value" SelectedValue="{Binding Key, Mode=TwoWay}"
IsEditable="False" IsReadOnly="True" />
SelectedValue="{Binding Key, Mode=TwoWay}"
This will change the SelectedItem to its SelectedValue.
Related
I have a ComboBox binded to DataContext SceneViewModel, but I want to fill it with data from an observableCollection from another ViewModel called GearViewModel.
How do I do this? or is this possible.
Here is the xaml
<UserControl x:Class="MoviePrepper.View.SceneView"
DataContext="{Binding SceneViewModel, Source={StaticResource Locator}}">
<Grid>
<ComboBox ItemsSource="{Binding to observableCollection in GearViewModel}}" SelectedItem="{Binding SceneCollectionView/Equipment, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</UserControl>
You can achieve this using a binding like this:
<ComboBox ItemsSource="{Binding GearViewModel.MyCollection, Source={StaticResource Locator}}"
SelectedItem="{Binding Equipment, UpdateSourceTrigger=PropertyChanged}"/>
Where the ItemsSource property binds to the GearViewModel.MyCollection property in your Locator, and the SelectedItem binds to the SceneViewModel.Equipment (as set by the DataContext of the UserControl).
It is not clear exactly what property you had in mind for binding on the SelectedItem property, so I made some assumptions.
Anywho, that should solve the problem with binding your ItemsSource property to a different view model.
If i load string value in dependency property "Text" of ComboBox. ComboBox does not pair string value with ItemsSource objects and i don't have SelectedItem filled.
Need SelectedItem for ToolTip!!
<ComboBox x:Name="FieldComboBox" IsEditable="True" IsTextSearchEnabled="True"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="DataCode"
ItemsSource="{Binding FieldAlternative.FieldParts[0].DataItems}"
ToolTip="{Binding Path=SelectedItem.Description, ElementName=FieldComboBox}"/>
If i've empty Text and write, it works fine. If i've opened form with value in Text i have SelectedItem null but value Text is displayed.
Any solution how to forced pairing Text with objects in ItemsSource to fill SelectedValue, or any better solution of my problem.
Thx
You can set a default value to your combobox by the SelectedItem property which will be binded to your Text Field in your ViewModel:
SelectedItem="{Binding Path=Text, Mode=TwoWay}"
So your combobox element becomes like this:
<ComboBox x:Name="FieldComboBox" IsEditable="True" IsTextSearchEnabled="True"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=Text, Mode=TwoWay}"
DisplayMemberPath="DataCode"
ItemsSource="{Binding FieldAlternative.FieldParts[0].DataItems}"
ToolTip="{Binding Path=SelectedItem.Description, ElementName=FieldComboBox}"/>
I try to bind a selected item in my datagrid to some textboxes.
Sadly the textboxes wont be updated on change.
If you need more Informations fell free to ask.
In my view i try to bind the the data of the selected Item of the Datagrid to the Textboxes.
in the Textboxes there can be a new employee you want to add or one of the Datagrid that you want to edit.
<TextBox Name="TxtName" Text="{Binding Employee.LastName}" Grid.Column="1" Grid.Row="0"></TextBox>
<TextBox Name="TxtFirstName" Text="{Binding Employee.FirstName}" Grid.Column="3" Grid.Row="0"></TextBox>
<TextBox Name="TxtDateOfBirth" Text="{Binding Employee.DateOfBirth, StringFormat=d}" Grid.Column="1" Grid.Row="1"></TextBox>
<ComboBox Name="CmbGender" SelectedItem="{Binding Employee.Gender}" ItemsSource="{Binding Genders}" DisplayMemberPath="Short" Grid.Column="3" Grid.Row="1"/>
<DataGrid Name="GrdAllEmployees" ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee}" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="4" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChanged}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
In my ViewModel i set the Value of the Selected Employee to the Employee that is shown in the Textboxes and raise the Events for both.
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set
{
_selectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
_employee = _selectedEmployee;
NotifyPropertyChanged("Employee");
}
}
After this the values are correct on debugging. but the view will not be updated.
There is a much simpler way of displaying values from the selected item of the DataGrid, or in fact any collection control in WPF. That is to use the Selector.IsSynchronizedWithCurrentItem property. When you set this to true, then you can reference the selected item from that collection using the / notation, which means the current item. Try something like this:
<StackPanel>
<DataGrid ItemsSource="{Binding Employees}" IsSynchronizedWithCurrentItem="True" />
<TextBlock Text="{Binding Employees/Name}" />
</StackPanel>
This would display the Name property value from the currently selected item in the DataGrid. Further information... from the Binding.Path Property page on MSDN:
When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.
Property names and slashes can be combined to traverse properties that are collections. For example, Path=/Offices/ManagerName specifies the current item of the source collection, which contains an Offices property that is also a collection. Its current item is an object that contains a ManagerName property.
It worked for me after i replaced my own classes for the RelayCommand and ViewModelBase with the ones of MVVMlight, that i downloaded from nuget.
https://mvvmlight.codeplex.com/
I just had to change the NotifyPropertyChanged with RaisePropertyChanged.
But also thanks to #Sheridan for his advice.
I have a Silverlight application with a formular. The formular has a TextBox and a ListBox.
<TextBox Text="{Binding Value, Mode=TwoWay}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>
I focus the TextBox and write something into it. After this I select an item in the ListBox. The ViewModel seems to set "SelectedItem" BEFORE "Value". Why? How can I fix the order? I mean I need to process the TextBox before the ListBox.
Thanks
Unfortunately, that looks like a bug. Same example on WPF will cause the TextBox to be set before the ListBox. You would have to find another way of doing what you want by slightly changing the logic of how you app UI functions.
You can update your TextBox Text property binding on TextChanged event, not LostFocus how it is now. Here is a sample.
The TextboxBinding is by default updating on LostFocus, try changing your binding to this:
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>
Here's the Xaml for my combobox:
<ComboBox Grid.Column="4"
Grid.Row="3"
ItemsSource="{Binding Path=Users, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type cs:AdvancedSettingEditor}}}"
Margin="5"
x:Name="UserPicker"
SelectedValue="{Binding Path=StandAloneUserName, Mode=TwoWay}"
TabIndex="1"
Visibility="{Binding Converter={StaticResource InvertedBoolToVisibility}, Path=LoginRequired}" />
In the code behind, I have a simple ObservableCollection of strings:
public ObservableCollection<string> Users { get; set; }
The Users collection is loaded with string data from the database.
There is also a DependencyProperty that is bound to the window's DataContext that has a property called StandAloneUserName. The object stored in this property implements INotifyPropertyChanged.
When I run the program, the combo box has all of the names in the Users collection in the drop down list, but the box is blank. The control is not losing the value of the field, so it just doesn't know what to display.
How do I get my ComboBox to display the name that is in the StandAloneUserName property?
Tony
Set SelectedItem instead of SelectedValue
<ComboBox SelectedItem="{Binding Path=StandAloneUserName, Mode=TwoWay}" ... />
I'm assuming it's evaluating as "doesn't exist" since you don't have SelectedValuePath set to anything.