I have two properties, one which is a list of string and the other just a string.
private List<String> _property;
public List<String> Property
get
{
return new List<string>(){"string1", "string2"};
}
set{_property = value
}
public String SimpleStringProperty{get;set;}
I also have a Combobox defined in XAML as such
<Combobox ItemsSource="{Binding Property , Mode="TwoWay"}" Text="Select Option" />
Now the combobox correctly displays two options :"string1" and "string2"
When the user selects one or the other, I want to set SimpleStringProperty with that value. However, the 'value' im getting back from the combobox through the two way binding is not the selectedItem, but the List<String>. How can I do this right? I'm fairly new to wpf, so please excuse the amateurism.
<Combobox ItemsSource="{Binding Property}" SelectedItem="{Binding SimpleStringProperty, Mode=TwoWay}" Text="Select Option" />
That's untested, but it should at least be pretty close to what you need.
You need to bind to the String property using the SelectedItem property of the combobox.
<Combobox ItemsSource="{Binding Property}"
SelectedItem="{Binding SimpleStringProperty}"
IsSynchronizedWithCurrentItem="True"
Text="Select Option" />
What helped me:
Using SelectedItem
Adding UpdateSourceTrigger=PropertyChanged
IsSynchronizedWithCurrentItem="True" to be sure Selected item always synchronized with actual value
Mode=TwoWay if you need to update as from source as from GUI
So at the end best way, if source is
List<string>
Example:
<ComboBox
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding SomeBindingPropertyList}"
SelectedItem="{Binding SomeBindingPropertySelectedCurrently,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
Additional Info
Difference between SelectedValue and SelectedItem:
https://stackoverflow.com/a/4902454/2758833
https://stackoverflow.com/a/2883923/2758833
SelectedValuePath Documentation:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.selector.selectedvaluepath
SelectedValue updates possible bugs for .NET 4 and .NET 4.5:
https://stackoverflow.com/a/247482/2758833
Related
Heyo its me again,
<ComboBox ItemsSource="{Binding EnterpriseList, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedItem="{Binding Enterprise, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
DisplayMemberPath="Name"
IsEditable="True"
IsEnabled="{Binding EnterpriseIsEnabled, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Margin="3" Grid.Column="1">
does anyone know how i can bind the SelectedItem in this example to an Enterprise-Object?
I can select the enterprise in the combobox like I want it, and it delivers a enterprise-object too, but when i reload the view, the text of the combobox doesnt get set to the name of the enterprise-object.
I hope I have explained my problem well enough, my english is not that good, I usually speak german ...
Your XAML look ok. Please be aware that the item your assign to Enterprise must be one from the list EnterpriseList. The Combobox does compare object references not object contents e.g. the characters of strings.
I have a collection of Contact objects that I've bound as follows in a WPF form:
<ComboBox Name="Name"
Text="{Binding Path=Contact.FullName}"
ItemsSource="{Binding ContactsCollection}"
SelectedItem="{Binding Path=Contact, Mode=TwoWay}"
IsEditable="true"
IsTextSearchEnabled="True"
TextBoxBase.TextChanged="Name_TextChanged"/>
<TextBox Name="Position" Text="{Binding Path=Contact.Position}"/>
<TextBox Name="Phone" Text="{Binding Path=Contact.PhoneNumber}"/>
I'd like the contact to be selected when the user starts typing in the combo 'IsTextSearchEnabled=true'.
The problem is that I'd like the items in the collection to remain read-only. Once a contact has been selected, any text deletes or additions modify the contact name in the collection.
How can I bind a collection to a combobox, enable search and prevent edits to the collection?
I could be missing something here, but if you don't want an editable ComboBox, try not setting the ComboBox.IsEditable property to True. Using this simple code, I can display items in a ComboBox and make selections by typing (when the ComboBox is focused) without editing anything:
<ComboBox ItemsSource="{Binding Items}" IsTextSearchEnabled="True" Height="25" />
Thanks for your input. It sorted me out. Removing the SelectedItem property and setting Position and PhoneNumber in the PropertyChanged event was what I needed.
I have a List collection that when it is assigned has a collection of type short numbers. However how do I display the numbers on a WPF ComboBox?
I usually use the DisplayMemberPath property in XAML, but I cannot state a property because it isn't my own collection. (Such as List(T)....)
The XAML
<ComboBox HorizontalAlignment="Left"
ItemsSource="{Binding TheList}"
// This is wrong of course
DisplayMemberPath="."
C#
public List<short> TheList
{
get
{
return m_ListSID;
}
set
{
m_ListSID = value;
}
}
Any help would be grateful.
EDIT
Utter silliness...All answers are of course true and makes sense, it was just due that I forgot to trigger the update source for the Collection
ItemsSource="{Binding TheList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Apologises
Thanks
DisplayMemberPath is not needed here
<ComboBox HorizontalAlignment="Left" ItemsSource="{Binding TheList}" DisplayMemberPath="" />
You don't need to have any DisplayMemberPath
This is sufficient:
<ComboBox HorizontalAlignment="Left" ItemsSource="{Binding TheList}"/>
Don't set DisplayMemberPath at all and short should be converted to string
<ComboBox HorizontalAlignment="Left" ItemsSource="{Binding TheList}"/>
if no template is provided by default WPF will call ToString() on an item.
EDIT
You can find more details on how display content is created on the ContentPresenter MSDN page
I have my data grid "dgSubsytem" column defined like below
<my:DataGridComboBoxColumn x:Name="cmbSubSysSupplier_SRV" Header="Supplier" Width="160"
ItemsSource="{Binding RelativeSource}" SelectedValueBinding="{Binding SupplierId}" />
As you see from the code i am having a combo box inside a grid .
Item source of this combo box is a datatable which is bound to it in the code behind .
Item source of the grid also another datatable bound in code behind .
code of binding item source of combobox in code behind is as follows
cmbSubSysSupplier_SRV.ItemsSource = dsComboBox.Tables[3].DefaultView;
cmbSubSysSupplier_SRV.DisplayMemberPath="FullName" ;
cmbSubSysSupplier_SRV.SelectedValuePath = "SupplierId";
Problem is combo box itself not rendering . But I can see the value of the Supplier rendered as text . What is the problem?
There are 2 parts here:
List of values to be populated in ComboBox: ItemsSource, should be bound using a StaticResource, with a List<X> fields exposed from your ViewModel.
The actual value (here X) should be bound to SelectedItemBinding using binding to data item.
No binding in code behind required.
At what point does your code-behind stuff run?
You're setting the ItemsSource in two places - in the XAML and in the Code-Behind. Whichever one runs second will overwrite the value of the first one, so only the last value set will be used.
I suspect your XAML is getting run last, and RelativeSource is probably not a property on your DataContext, so your ComboBox ends up being bound to nothing.
To fix it, simply remove your ItemsSource binding in the XAML for the DataGridComboBoxColumn
<my:DataGridComboBoxColumn x:Name="cmbSubSysSupplier_SRV"
Header="Supplier" Width="160"
SelectedValueBinding="{Binding SupplierId}" />
In addition, the DefaultView of a DataTable will return an object of type DataView, and DataView does not have properties called FullName or SupplierId, so your SelectedValuePath and DisplayMemberPath properties won't work.
I'd recommend building a list of KeyValuePair<int,string> out of your data items, and bind your ComboBoxColumn.ItemsSource to that list, then switch the SelectedValuePath to "Key" and the DisplayMemberPath to "Value"
I personally fought with DataGridComboBoxColumn for long time and i think the way is to use DataGridTemplateColumn. Here is an exemple :
Looks a lot of code but evective.
Put the collection as resource :
<Grid.Resources>
<CollectionViewSource x:Key="StructuresCollection" Source="{Binding StructuresList, Mode=OneTime}"/>
</Grid.Resources>
<DataGridTemplateColumn Header="Structure" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Structures.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate >
<DataTemplate>
<ComboBox x:Name="CStructures" SelectedItem="{Binding Structures}" DisplayMemberPath="Name" SelectedValue="{Binding IDStructure, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding IDStructure}" ItemsSource="{Binding Source={StaticResource StructuresCollection}}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
I'm trying to bind a combobox to a ObservableCollection.When the form is displayed the combobox is empty.The same code with ObservableCollection of type string works perfectly. I've got a feeling that my XPath is wrong. Any suggestions are welcome:
XAML:
<ComboBox ItemsSource="{Binding ItemParameters, XPath=InnerXml/name,Mode=TwoWay}" SelectedIndex="0" Margin="2" VerticalAlignment="Top" HorizontalContentAlignment="Stretch" Grid.Row="1" Grid.Column="1" Height="24" />
ObservableCollection XmlNode :
public ObservableCollection<XmlNode> _itemParameters = new ObservableCollection<XmlNode>();
public ObservableCollection<XmlNode> ItemParameters
{
get { return _itemParameters; }
set { _itemParameters = value; }
}
The combobox should display the name attribute of each XmlNode in the collection:
Update:
I've tried using DisplayMemberPath in two different ways, but the combobox still contains no data:
DisplayMemberPath="{Binding XPath=name}" ItemsSource="{Binding ItemParameters}"
DisplayMemberPath="{Binding XPath=InnerXml/name}" ItemsSource="{Binding ItemParameters}"
Solution:
This did the trick, hope it helps someone else as well:
<ComboBox DisplayMemberPath="#name" ItemsSource="{Binding ItemParameters}"
First of all you are setting Path and XPath at the same time, which are conficting properties, secondly you bind the ItemsSource, which has nothing to do with what you want to show inside the item. Either use DisplayMemberPath or an ItemTemplate for that, the ItemsSource should just be bound to ItemParameters.