I know there is a few topics on this problem but haven't find any solutions to this problem I have..
I have a ViewModel with an observable collection and I want to bind this collection to a combo box. However, there is no selected item, no index, just the collection itself.
in the XAML I have
ComboBox ItemsSource="{Binding OSCollection}" DisplayMemberPath="OSCollection.Name"
I believe the trouble lies with the bold above, I want to get a property from the collection called name, but like I say - no item will be selected before the bind.
I could use a foreach or something to extract the properties from the collection but I don't think this is the MVVM and WPF way.
Any help would be grateful.
Thanks
DisplayMemberPath specifies the path to the display property.So it should be Name not OSCollection.Name
ComboBox ItemsSource="{Binding OSCollection}" DisplayMemberPath="Name"
In addition to Sajeetharans comment:
When binding to a List of Type T, DisplayMemberPath will always refer to the Name of a Property of T. In your case it is only "Name"
Related
I am having a furious struggle with the WPF Combobox in our bi-languge application.
I have the combobox binded to a collection. I have a button that replaces the values of the collection with their corresponding string values in another language.
What is the problem: I select a value from the drop down list. I change the language, by pressing a button, then the displayed value remains on the old language, but when the drop down is dropped the values in in are replaced with the right ones.
Here is my XAML:
<ComboBox x:Name="ProjectClassComboBox"
Width="150"
ItemsSource="{Binding Path=ProjectClassCollection}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding Path=RegionContext.CurrentItem.ClassNomenclatureId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
Update: Because it is asked in the comments I must add that
the collectionis a custom class of ours, DERIVED from ObservableCollection, that is fairly complex. The collection items must be implementing INotifyPropertyChanged, and the collection has a listener to the PropertyChanged event of each item.
It just looks like the displayed text of the combo is not updated, when the drop down list and the selected item value is updated.
Binding ObservableCollection (and derrived class too) works only in case where you add or delete items, cause that's the action that invokes change event. If you need to manipulate data inside collection I suggest using BindingList. Maybe some kind of wrapper would be solution for you.
Do one thing. In the button click,
1. get the selected index in the combo box
2. Replace all the strings in the collection
3. set the selecteditem property of the combobox using the selected index that we have stored earlier in the step 1.
So, it's a bit late but we just encountered the same problem on a project that needs to support multiple languages.
Our solution was to return a new instance of ObservableCollection on the property getter.
So, your code should look like this:
<ComboBox x:Name="ProjectClassComboBox"
ItemsSource="{Binding Path=ProjectClassCollection}"/>
And in your ViewModel:
public ObservableCollection<Project> ProjectClassCollection
{
get {return new ObservableCollection<Project>(){_projectClassCollection};}
set {...}
}
This code is a quick snippet from my memory. It will not work if you just copy-pasta, but the idea is that another collection instance worked for us.
We tried to call OnPropertyChanged(nameof(ProjectClassCollection)) but that didn't work. We tried to set UpdateSourceTrigger=PropertyChanged in XAML but that didn't work either. Having a new instance worked.
Hope this helps and saves you time, cheers!
Does anyone know how I can sort a Datagrid when the Itemsource of the grid changes? i.e. if I have a DataGrid of products, and another grid of product versions, when I select a product, the ItemSource of the product version DataGrid will change so I would like to do a sort before the data appears inside the Product Versions DataGrid.
The way I do the sorting at the moment is.
<CollectionViewSource x:Key="cvsProductVersions"
Source="{Product.ProductVersions, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Filter="CollectionViewSource_Filter">
<!--<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Build1" Direction="Descending"/>
</CollectionViewSource.SortDescriptions>-->
</CollectionViewSource>
I think I need to use
CollectionViewSource.GetDefaultView(dgProductVersion.ItemsSource).Refresh();
However, I need an event which basically means "Run this code once a new itemsource is applied to the table.
Cheers
At some stage, I'm guessing that you set a collection as the ItemsSource property value for your CollectionViewSource. Why don't you just sort it using LinQ before you assign it to the CollectionViewSource?:
SomeCollection = new ObservableCollection(SomeCollection.OrderBy(i => i.Build));
You can refresh a CollectionViewSource directly, but it isn't generally what users want because it does a complete refresh... you could try something like this:
(dgProductVersion.ItemsSource as ListCollectionView).Refresh();
A third option can be found in the ItemsControl: 'E' is for Editable Collection on the Dr. WPF website.
I can't figure this out, consider the following code:
<ListBox Width="200"
ItemsSource="{Binding CurrentArticle.ArticleCategories}"
DisplayMemberPath="{Binding Category.Name}">
</ListBox>
ArticleCategories is a table in my database that contains 2 foreign keys, 1 to Article and 1 to Categories, so ArticleCategories is a list that contains Articles and Categories.
I want to show which categories the current article(CurrentArticle) have in this listbox and I can't figure out how to do so. I want to show Category.Name for each Category in the ListBox.
Right now, the listbox is showing "Data.ArticleCategory" because it dont know how to display it.
I have tried DisplayMemberPath="Category.Name" without success.
Do I need to use some sort of Data Template, if so, how?
Thank you.
DisplayMemberPath is not a field where you add a binding, its just the name of your Property on the given Item. DisplayMemberPath="Name" should be enough.
You don't need a binding:
DisplayMemberPath="Category.Name"
EDIT: since you're binding ItemsSource to CurrentArticle.ArticleCategories, I assume that the items of your ListBox are objects of type Category? in that case the path should be just "Name", not "Category.Name".
You can set the ListBox.ItemTemplate with a datatemplate that looks the way you like:
http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplate.aspx
I've got combo box bound to a custom collection type - its basically an overridden ObservableCollection which I've added a facility to update the underlying collection (via Unity).
I don't want to confuse the issue too much, but thats the background.
My xaml looks like this
<ComboBox ItemsSource="{Binding Manufacturers}" DisplayMemberPath="Name" SelectedValuePath="ID" SelectedValue="{Binding Vehicle.ManufacturerID}" />
And in my overridden collection i was doing this.
var index = IndexOf(oldItem);
this[index] = (T)newItem;
I had hoped because it was bound by value, that inserting the new object(which had the same id) over the old object would work. But it seems that although its bound by SelectedValue it still knows that its being swapped for a different one. The combo just looses its selection.
Can anyone help please?
I assume that your oldItem was the SelectedValue in this case?
When you remove this item, your binding gets updated instantly. So removing that value from the list will clear your selection.
If you want to replace the item, you might want to try to get the SelectedValue, save it in a variable, and set the SelectedValue later when you have replaced your item, like so:
object oldValue = SelectedValue;
//Do awesome stuff to replace things
SelectedValue = oldValue;
HTH
I have a combo box which is populated on selection's from two other combo'.
No problem I have this working.
Problem is I only want to activate the Selected Item binding after this has happened.
Here is my combo
<cuc:ComboBox Name="GopLenTypeCombo" Width="240" Height="24"
IsSynchronizedWithCurrentItem="True"
SelectedValue="{Binding Mode=TwoWay, Source={StaticResource ProfileDataProvider}, XPath=GopLenType}"
IsEnabled="False"/>
How do I stop the SelectedValue binding working untill I have populated the combo ?
I don't know whether this is possible in pure XAML, but if you have an underlying ViewModel, this wouldn't be too hard:
What you would need to do is to bind your third ComboBox to a property on the ViewModel (let's call this property Combo3Items).
You would also need to bind the two first ComboBoxes to properties on the same ViewModel (let's call these Combo1Items and Combo2Items, respectively). In addition to that, you could bind both of these ComboBoxes' SelectedValue to properties on the ViewModel, so that the ViewModel knows which items are selected.
Initially, Combo3Items would be empty, but as soon as the two bound SelectedValues are properly assigned, you can fill Combo3Items and raise an INotifyPropertyChanged event.
The MVVM architecture is very powerful. If you don't already know it, you can read more about it here.