Binding to a CollectionViewSource Question - wpf

My issue goes like that:
I have 2 ListBox:
one is bound to a collection called photos of type Photos and the other is bound to a CollectionViewSource which is bound to the same photos collection.
listBox1 -> photos (here the listBox1 is bound to the Default CollectionView of photos, of course and not directly to photos.)
ListBox2 -> cvs -> photos
both collection (the default one and my CVS) having a filter that reduce the items they show from 8 items to 5 items.
now i have 2 labels. one is bound to the Count property of the photos object and the other one is bound to the Count property where the source is the cvs (my CollectionViewSource) object.
the first label show the number 8 and as i see it, it is because the Count of photos stays 8 even though i am filterring it's default CollectionViewSource.
the second label shows the number 5.
what i learnt about binding to a cvs is that WPF unwrapps the source object from the cvs and the Path=Count is relevant to the underlying object which is photos and the number here should be 8 also.
does someone can explain me where i am worng?
thanks!

The binding will not bind to the source collection but the view. The collection view also has a Count property which returns the number of items in the (filtered) view rather than in the original collection.
(You can use the debugger to see that the View property of the CollectionViewSource normally will be an object which is an instance of CollectionView or one of its subclasses. The binding will implicitly bind to View.Count)
To bind to the original count use the path SourceCollection.Count.

Related

WPF MVVM : get a collection of cell-data corresponds to a column

Is there any way to get DataGridColumns cells-data as a collection of cell-data corresponds to this column?
Note that I'm using MVVM and my datagrid is being dynamically built by DataGridColumn collection!
Thanks!
If you are really using MVVM, then you will know that you should have all of the data that is displayed in the view in your related view model. If that is correct, then you will have a collection that is data bound to the DataGrid.ItemsSource property. As we work with data in WPF and not UI elements, then you can get a collection that contains all of the values from one column using LinQ.
Let's say that you have a column (and therefore a property of your data type) that you want to single out. Let's say that that property is a string and named Name. You can gather all of the values of that property from each item in the collection like this:
List<string> names = yourCollection.Select(i => i.Name).ToList();
If it were an int property named Age, you could do this... and so on:
List<int> ages = yourCollection.Select(i => i.Age).ToList();

How does binding to collections really work?

Well, I'm confused.
If my control has dependency property ItemsSource of IEnumerable type and user binds collection to it what object do I have in DependencyPropertyChangedEventArgs.NewValue?
As far as I know CollectionView is implicitly created for collections and I expect args.NewValue to be of type ICollectionView.
From this blog:
When a user binds a WPF property to a collection of data, WPF
automatically creates a view to wrap the collection, and binds the
property to the view, not the raw collection. This behavior always
happens, and is independent of CollectionViewSource.
But debugger (VS 2012, .net v.4.0) shows me that I receive original raw collection in NewValue. (BindsDirectlyToSource is not set and equals false by default)
How can this be?!
I cannot understand how in this case WPF controls support sorting, grouping and filtering.
How and when is CollectionView injected and used?
Maybe the following extract from the Remarks section in CollectionView answers your question:
In WPF applications, all collections have an associated default
collection view. Rather than working with the collection directly, the
binding engine always accesses the collection through the associated
view. To get the default view, use the
CollectionViewSource.GetDefaultView method. An internal class based on
CollectionView is the default view for collections that implement only
IEnumerable. ListCollectionView is the default view for collections
that implement IList. BindingListCollectionView is the default view
for collections that implement IBindingListView or IBindingList.
Alternatively, you can create a view of your collection in Extensible
Application Markup Language (XAML) by using the CollectionViewSource
class and then bind your control to that view. The
CollectionViewSource class is the XAML representation of the
CollectionView class. For an example, see How to: Sort and Group Data
Using a View in XAML.
So if you do not explicitly bind to a CollectionViewSource, a collection binding is always made to the original collection (what you get in NewValue), but access to the collection (e.g. get an item by index) is always done through the default view. Therefore the statement "binds the property to the view, not the raw collection" is not exactly true.
A quick test revealed that GetDefaultView returns a System.Windows.Data.ListCollectionView for my bound ObservableCollection.

Silverlight GridView data update

I have a datagrid wich bunded on IEnumerable collection.
Some properties of each item of this collection contains "id". I use convertors for show strings for this "id". There is now relations between tables with "id" and names for each id.
So i can cheange name, but how can i refresh grid without bounded collection cheanging?
ThnX.
Sorry for my English.
I think that you must implement INotifyPropertyChanged In your Object contained in the IEnumerable collection.
with this implementation, the interface detect changes automaticly when object properties changes and vis versa.
Regards

Data Binding with WPF and MVVM/Model-View-ViewModel

I'm having difficulty correctly Data Binding my models in the view. I have a MainWindowViewModel which contains a list of AlbumViewModels. Each AlbumViewModel holds an AlbumModel. So I have multiple albums and I need to display information in an ObservableCollection in the AlbumModel. I have two ListBoxes. ListBox1 holds the list of AlbumViewModels that are in my MainWindowViewModel. My second ListBox I want to display the ObservableCollection from the current selected item from the AlbumViewModel.AlbumModel. How can I do this? I've tried binding the DataContext of ListBox2 to the ListBox1 element, along with SelectedItem as the path but that returns 'AlbumViewModel'. Is there anyway to bind ItemsSource of a ListBox to the binding of the DataContext, but in this case binding it to [DataContext].AlbumModel.ObservableCollection or something?
I apologise if it sounds rather complicated!
You can use the fact, that when you bind to a collection, WPF wraps collection to CollectionView. And this guy has CurrentItem.. Bea had good article: How can I sync selection of two data bound ListBoxes? and Dr.WPF is amazing (as usual): ItemsControl: 'C' is for Collection.

How do I loop through a set of items in a databound Silverlight control such as the ListBox?

I have a silverlight ListBox that has it's ItemsSource set. From the C# code behind I want to loop through each ListBox item and change the value of the text and access controls that are in the ListBox ItemTemplate. How would I do that?
ListBox controls in silverlight are bound to an ienumerable type, so that if any value in the ListBox changes, the underlying data is changed and vice versa depending on what type of binding you require. To effectively iterate the items you'll want to iterate through the enumerable object you've bound to.
You can get to the collection by accessing the ListBox.ItemsSource property and change the text of appropriate items, perform LINQqueries etc. If you have bound the controls correctly, saving the collection should update the list.
Hope this helps!

Resources