EDIT
Solution was actually a proper setting of SelectedItem, SelectedValue and SelectedValuePath properties.
<ComboBox
Grid.Column="1"
Padding="5"
DisplayMemberPath="PositionName"
IsSynchronizedWithCurrentItem="False"
ItemsSource="{Binding Positions, Mode=OneWay}"
SelectedItem="{Binding SelectedOperatorPosition, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding SelectedOperatorPosition.PositionName}"
SelectedValuePath="PositionName" />
QUESTION
I am trying to bind ComboBox SelectedValue with DataGrid SelectedItem using MVVM pattern.
ComboBox ItemSource is Shifts property. I want it's SelectedValue to be bound with SelectedShift property, which is updated each time user selects another OperatorModel from DataGrid.
Although SelectedOperator setter sets SelectedShift value to SelectedOperator.Shift, ComboBox doesn't get updated.
View
Debugging ViewModel Property setter
My ViewModel:
private Operator selectedOperator;
public Operator SelectedOperator
{
get
{
return selectedOperator;
}
set
{
selectedOperator = value;
if (selectedOperator != null)
{
SelectedShift = selectedOperator.Shift;
}
OnPropertyChanged(nameof(SelectedOperator));
}
}
private Shift selectedShift;
public Shift SelectedShift
{
get
{
return selectedShift;
}
set
{
selectedShift = value;
OnPropertyChanged(nameof(SelectedShift));
}
}
XAML:
<ComboBox
Grid.Column="1"
Padding="5"
DisplayMemberPath="Name"
ItemsSource="{Binding Shifts}"
SelectedValue="{Binding SelectedShift}"
SelectedValuePath="Name" />
i think you should use SelectedItem="{Binding SelectedShift}
Related
I have seen a couple of posts in this site similar to my issue like this one and this one But I haven't gotten this to work for me.
I have a datagrid bound to by a list of objects of type Foo and I have a combobox added for each row. The ComboBox ItemSource is not a part of the Foo class but rather it's created in the view model. I know doing so means that this combobox is the same for every row but isn't there a way in my Xaml to filter SelectedItem to just the row?
Here is my Xaml:
<DataGridTemplateColumn Header="Foo Column" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Mode=OneWay,Path=DataContext.FooCollection,
RelativeSource= {RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}}"
SelectedItem="{Binding DataContext.SelectedComboBoxItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
RelativeSource= {RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Here is my ViewModel:
public ObservableCollection<string> FooCollection
{
get
{
return _FooCollection;
}
set
{
if (_FooCollection != value)
{
_FooCollection = value;
RaisePropertyChanged(nameof(FooCollection));
}
}
}
private ObservableCollection<string> _FooCollection = new ObservableCollection<string>();
public string SelectedComboBoxItem
{
get
{
return __SelectedComboBoxItem;
}
set
{
if (_SelectedComboBoxItem != value)
{
_SelectedComboBoxItem = value;
RaisePropertyChanged(nameof(SelectedComboBoxItem));
}
}
}
private string _SelectedComboBoxItem = string.Empty;
I am seeing my combobox collection populated but when I make a selection every other combobox gets the same value. Can anyone help me understand what I am doing wrong? Many thanks.
To make your code working you'll need to bind the SelectedComboBoxItem to DataGrid item. In your case this is a Foo type
I have a datagrid bound to by a list of objects of type Foo
Place this code to Foo class
public string SelectedComboBoxItem
{
get
{
return __SelectedComboBoxItem;
}
set
{
if (_SelectedComboBoxItem != value)
{
_SelectedComboBoxItem = value;
RaisePropertyChanged(nameof(SelectedComboBoxItem));
}
}
}
private string _SelectedComboBoxItem = string.Empty;
and update your binding according that
SelectedItem="{Binding SelectedComboBoxItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
I write this combobox
<ComboBox
x:Name="ComboBoxRole"
SelectedItem="{Binding ApplicationModel.CategoryName}"
ItemsSource="{Binding Categories}"
Style="{StaticResource ComboBoxStyle}" Text="Choose"
/>
for this model
public class CategotyModel : INotifyPropertyChanged, IDataErrorInfo
{
private string id;
private string name;
public string Id
{
get => id;
private set
{
id = value;
NotifyPropertyChanged("Id");
}
}
public string Name
{
get => name;
private set
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
for Item source create this property
public IList<CategotyModel> Categories
{
get
{
var categoriesDTO = _categoryManager.GetAllCategories();
this.categories = mapper.DefaultContext.Mapper.Map<IList<CategotyModel>>(categoriesDTO);
return categories;
}
}
it work fun, but I don't know how sent to combo just 1 parametre , because I take "AppStore.WPF.MVVMLight.Models.CategotyModel" object.
Note: I take the result from server. it's never mind.
(without foreach the IList<CategoryModel> and write to list of the string - i think it's bad way).
Edit
<ComboBox
x:Name="ComboBoxRole"
SelectedItem="{Binding ApplicationModel.CategoryName}"
SelectedValuePath="Name"
DisplayMemberPath="Name"
ItemsSource="{Binding Categories}"
Style="{StaticResource ComboBoxStyle}"
Text="Choose"
/>
You need to fix a few things in your ComboBox: To display the Name properties of the items, add DisplayMemberPath="Name". To select just the name property of the selected item instead of the whole object, add SelectedValuePath="Name", and bind ApplicationModel.CategoryName to SelectedValue instead of SelectedItem.
SelectedItem will still be the whole object, even when SelectedValuePath is in use.
<ComboBox
x:Name="ComboBoxRole"
SelectedValue="{Binding ApplicationModel.CategoryName}"
SelectedValuePath="Name"
DisplayMemberPath="Name"
ItemsSource="{Binding Categories}"
Style="{StaticResource ComboBoxStyle}"
Text="Choose"
/>
you want DisplayMemberPath="Name"
<ComboBox
x:Name="ComboBoxRole"
DisplayMemberPath="Name"
SelectedItem="{Binding ApplicationModel.CategoryName}"
ItemsSource="{Binding Categories}"
Style="{StaticResource ComboBoxStyle}"
Text="Choose"/>
I have a listbox and a textbox, I want the textbox show data according to the listbox selection. The problem is I already have the listbox binding to an object like this:
<ListBox x:Name = "listbox" SelectionMode="Single" ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct}" DisplayMemberPath="{Binding SelectedProduct}">
The textbox which I want to populate data is not the property of SelectedProduct that I binding to, it only has relation to the listbox index. For example:
private int[] _InputStartAddress = new int[20];
textbox.text = _InputStartAddress[listbox.SelectedIndex];
The ViewModel of SelectedProduct:
private Product selectedProduct;
public Product SelectedProduct
{
get { return selectedProduct; }
set
{
if (selectedProduct != value)
{
selectedProduct = value;
NotifyPropertyChanged();
}
}
}
What should I do to achieve this?Thanks!
bind directly to ListBox property using ElementName:
<ListBox Name="ListProducts" SelectionMode="Single" ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct}" DisplayMemberPath="{Binding SelectedProduct}">
<TextBox Text="{Binding Path=SelectedIndex, ElementName=ListProducts}"/>
I want to bind a ComboBox item to a string, but it does not work. My code is below.
Code in view:
<ComboBox
SelectedValuePath="content"
SelectedItem="{Binding ProductName}"
......
<ComboBoxItem>1111111111</ComboBoxItem>
<ComboBoxItem>2222222222222</ComboBoxItem>
<ComboBoxItem>333333333333</ComboBoxItem>
</ComboBox>
Code in view model:
private string _productName;
public string ProductName
{
get { return _productName; }
set
{
if (_productName != value)
{
_productName = value;
RaisePropertyChangedEvent("ProductName");
}
}
}
I assume you want to get the text from the ComboboxItem and not the ComboBoxItem iteself.
So you are binding the wrong information. This should work.
<ComboBox
SelectedValuePath="content"
Text="{Binding ProductName}"
......
<ComboBoxItem>1111111111</ComboBoxItem>
<ComboBoxItem>2222222222222</ComboBoxItem>
<ComboBoxItem>333333333333</ComboBoxItem>
</ComboBox>
Selected Item is of type ComboBoxItem, it will not accept String.
If you want to display product name in some other place try maybe something like this:
<TextBox Text="{Binding ElementName=my_ComboBox, Path=SelectedItem}"/>
Just a suggestion.
You already use a binding for the SelectedItem, why don't you set up another binding for the Items using the ItemsSource? So you would not need to add them statically in your view.
In addition you would not have the trouble to wonder whether you deal with instances of ComboxItem or String with your SelectedItem binding.
In case of the binding via ItemsSource you can be sure that the SelectedItem is a string.
Here is the code:
<ComboBox
SelectedValuePath="content"
SelectedItem="{Binding ProductName}"
ItemsSource="{Binding ProductNames}"
</ComboBox>
In your view model (or code behind) you define the ProductNames:
public String[] ProductNames
{
get
{
return _productNames;
}
set
{
if (_productNames!= value)
{
_productNames = value;
RaisePropertyChangedEvent("ProductNames");
}
}
}
String[] _productNames;
public NameOfConstructor()
{
List<String> productNames = new List<String>();
productNames.Add("A");
productNames.Add("B");
productNames.Add("C");
ProductNames = productNames.ToArray();
}
If it was possible that the list of names changes during execution, I would use a ObservableCollection<string> instead String[].
It should be like this
Create an observable collection of Product in View Model. Lets Say ProductCollection
Bind to the ComboBox ItemSource as given below
<ComboBox Name="productComboBox" Width="200" Height="30" ItemsSource="{Binding ProductCollection}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ProductName}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
if you want to show in textbox somewhere
use this
<TextBox Text="{Binding ElementName=productComboBox, Path=SelectedItem}"/>
*Intro: *
I'm working with a standard MVVM framework and I have two listboxes from which I want to be able to select one item from. The listboxes are binding to different ObservableCollections of the same class.
After binding to the ViewModel, I want to be able to represent the selected Item on the same window, from either of the Listbox depending on which item I am selecting.
ViewModel -
private KisesaSearchResultViewModel _selectedPerson;
public KisesaSearchResultViewModel SelectedPerson
{
get
{
return _selectedPerson;
}
set
{
_selectedPerson = value;
OnPropertyChanged("SelectedPerson");
}
}
private KisesaSearchResultViewModel _selectedSearch;
public KisesaSearchResultViewModel SelectedSearch
{
get
{
return _selectedSearch;
}
set
{
_selectedSearch = value;
SelectedPerson = value;
OnPropertyChanged("SelectedSearch");
}
}
private KisesaSearchResultViewModel _selectedMatch;
public KisesaSearchResultViewModel SelectedMatch
{
get
{
return _selectedMatch;
}
set
{
_selectedMatch = value;
SelectedPerson = _selectedMatch;
OnPropertyChanged("SelectedMatch");
}
}
XAML -
<ListBox ItemsSource="{Binding Path=MatchedMembers, Mode=OneWay}"
ItemTemplate="{StaticResource SearchResult}"
SelectedItem="{Binding SelectedSearch}">
</ListBox>
<ListBox ItemsSource="{Binding Path=SelectedMatchList, Mode=OneWay}"
ItemTemplate="{StaticResource SearchResult}"
SelectedItem="{Binding SelectedMatch}">
</ListBox>
I want to display information as such:
<TextBlock Grid.Row="1" Text="{Binding Path= SelectedPerson.FullName}" FontSize="18" FontWeight="Bold" Style="{StaticResource PInfo}" />
<TextBlock Grid.Column="0" Grid.Row="2" Style="{StaticResource Info}" Margin="30,0,0,0" Text="{Binding Path=SelectedPerson.Age}"/>
Question:
I need to have SelectedSearch and SelectedPerson because I want to be able to change SelectedPerson independtly. At this point, the SelectedPerson is getting set by the SelectedSearch setter, but it is not binding to the Textblocks. I am using OnPropertyChanged, but do I need to do something else like use an Event Handler? Also, slightly unrelated, but can I restrict a WPF window so that only one item from two different Listboxes is selected at a time?