I've been binding a Collection to a ListView and now I'm curious about the way this happens for WPF.
The main question is How WPF accesses the items of the collection? GetEnumerator is never called when binding.
Thanks
In my WPF GetEnumerator is called. I do not know how you came to this conclusion but if you implement the interface and set breakpoints you can see as much. The binding system however also checks for IList and may access items via the Count & indexer, GetEnumerator seems to be called regardness though.
Related
I have a Dictionary whose ValueCollection consists of classes, which is exposed as a property in my VM, and bound to a DataGrid on the UI. My problem is that the Dictionary is populated asynchronously (it's actually an ObservableDictionary, so I can monitor change events), and no results ever show up in the grid. I'm raising the PropertyChanged event in the VM for the property the DataGrid is bound to whenever an item is added to the Dictionary, but can't get any results. I have verified that the events do fire.
If I use a straight ObservableCollection instead of an ObservableDictionary, everything is fine, and I don't need to raise PropertyChanged even, but I really wanted to use Dictionary to hold my collection to keep a unique key on each entry.
Am I doing something wrong, or is there a workaround with a different collection that I could use? I've also tried calling .ToObservable() or .ToEnumerable() on the value collection for binding.
The problem is that your ObservableDictionary probably implements INotifyCOllectionChanged (good), but your ObservableDictionary.Values does not.
Override the non generic IEnumerable.GetEnumerator method on your dictionary to return just the values instead of KeyValuePairs and bind the dictionary to your grid.
The problem was solved by returning Dictionary.Values.ToList() in my VM instead of just .Values, .Values.GetEnumerator(), or .Values.ToObservable(). I did have to still raise PropertyChanged in my VM for the VM property returning the list.
Look at this:
<ItemsControl ItemsSource="{x:Static local:Cache.Colors}" />
This binds the ItemsControl to a static property called List. In this case, the Colors property is part of a class called Cache.
But there is a problem. When you bind in this way, the Colors property is called during the Initialize method, prior to when Security is established in the application.
Because Security has not been established, then calling Colors results in an exception as Security is a requirement for successfully calling the data service.
The solution moves this from XAML to code behind and ensures it is executed in the Loaded event instead of in the constructor during Initialize.
The real problem here is, I would like to do this in XAML. Is it possible?
I have typically solved this by having the ItemsSource being bound to implement the INotifyCollectionChanged interface. At initialization the items source would be empty, and then at load time the items source is populated. The population of the items source raises the collection changed event, causing your items control to rebind/add the new items in the source.
My solution was to run it in the App.xaml.cs before anything else.
I've run into an issue I was surprised I couldn't find any discussion about (except WPF MVVM ComboBox SelectedItem or SelectedValue not working maybe).
I have a MVVM form that has 2 ctors, one is for "new item creation", the other is for "item modification". I have a combobox that represents one of the item's properties.
In the modification ctor, the property bound to ItemsSource is initialized, and then the property bound to SelectedItem is set. But nothing is selected in the UI, unless I delay (even a tiny bit) the SelectedItem set.
How can I solve this ? I decently can't keep a timer with a totally random interval to fix the issue :D
Thank you for your help
It seems like the elegant way to ensure the ItemsSource is initialized before I set the SelectedItem from VM is to have the binding source of ItemsSource (whatever it is) declared in my view resources.
I'm sure someone can lead me to the light now that I've pointed that out.
I have tried with a CollectionViewSource but didn't find the way to use its Filter capability without breaking the MVVM pattern. Plus I don't know how to re-raise the Filter as I used to with ICollectionView.Filter (filtered-out items depend on another combobox selection, nothing really fanciful imo).
Perhaps the resource declared in the view and used as ItemsSource has not necessarily to be a CVS, I'm looking for suggestions here.
--Edit--
I found out that the IsSynchronizedWithCurrentItem="True" solution spread all over the web is actually working. I was mislead because it didn't fix my problem at first try due to a remaining SelectedValuePath that wasn't used anymore on my control.
public MyViewModel()
{
this.Items = ...;
//this.SelectedItem = ...;
// select in separate message so that the ItemsSource has definitely been set
this.Dispatcher.BeginInvoke(delegate
{
this.SelectedItem = ...;
});
}
I've been exploring WPF and XAML for a while now, but have hit a slight stumbling block revolving around binding to a method.
My situation is:
There is a ComboBox bound to a DataTable. There is a ListBox bound to the return value of a method (GetDates) via an ObjectDataProvider. One of the input parameters of the method GetDates is an Id stored in the ComboBox/DataTable.
How can I bind a MethodParameter in the ObjectDataProvider to a particular value of the SelectedItem of a ComboBox (in this case, the SelectedItem is of type DataRowView)? Alternatively, am I missing a better way of solving this problem?
I can see ways out of it by using the code-behind, but I'd like to know if there's a more XAML-y solution. It's always useful to pick up little tips and tricks, even if it turns out not to be the best fix to this problem.
http://msdn.microsoft.com/en-us/library/system.windows.data.objectdataprovider.methodparameters.aspx
This seems to describe what I need - although it's actually trying to answer a different problem.
(Aside: Is it just me or is that example on MSDN trying to do too much all at once?)
By binding the ItemsSource of the ComboBox to a DataTable, and the SelectedItem of the ComboBox to a MethodParameter (with a converter to extract the value I need from the DataRowView), the ObjectDataProvider will have the parameter it needs.
It would probably be easier to read/follow/maintain if I just hooked into the ComboBox.SelectionChanged event.
It seems that others have had variations on this question, but from what I can tell it hasnt been addressed for folks using collections in a single view model.
I have a VM that contains an ObservableCollection of objects, not a VM for each object. Therefore I dont think I can use the SelectedItem bool that is often discussed because I dont think I can bind to the property on the collection's objects...just the properties on the VM.
So I've got the whole thing pretty well written with no code-behind and minimal coupling, but when a new item is added to the collection, which is bound to the treeView, I need to select that item.
Ideas?
Thanks!
When thinking about this. You should really build a wrapper for every element of the tree view that has the IsSelected bool on it as well as the IsExpanded bool they make life so much easier for displaying the data. You could even just add them to your class and use them from there.
Josh Smith has an article on CodeProject where he suggests creating a ViewModel object to represent each node of the TreeView, and then autowires them up as needed.
http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx