I have a Model with one of it property being Order with is a type of int. The model is put inside an ObservableCollection say for example ModelList is bound to a listbox.
Using this code
<CollectionViewSource Source="{StaticResource ModelList}" x:Key="SortedItems">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Order"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
Then this list is Bound to a listbox using
<ListView ItemsSource="{Binding Source={StaticResource SortedItems}}" />
Works Fines. But I want to change the order of the list by its Order property, that is when i change the Order via code I want the listbox to reflect the change.
How can I achieve this.
In order to resort a CollectionViewSource, you need to update the SortDescriptions property
To access your CollectionViewSource from code, declare it in your viewmodel and bind to it (instead of declaring it in XAML). For items in the visual tree, you can use x:Name, though this does not seem to work from a Resources tag, at least via initial testing
Related
I have created a user control containing a ListBox which is bound through a CollectionViewSource. The ListBox has CheckBoxes for the user to do multiple selection on. I would like the list to be sorted with the selected CheckBoxes at the top. I am hoping for this to work as soon as the user selects or unselects something. I can't seem to find anything thing that does this through xaml. What am I doing wrong?
In my xaml
<CollectionViewSource x:Key="SortedItems"
Source="{Binding Items, ElementName=Selector}"
IsLiveSortingRequested="True">
<CollectionViewSource.LiveSortingProperties>
<System:String>IsSelected</System:String>
</CollectionViewSource.LiveSortingProperties>
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="IsSelected"
Direction="Descending" />
<scm:SortDescription PropertyName="CodeDescriptionText" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
and my list box
<ListBox x:Name="ItemsControl"
SelectionMode="Multiple"
ItemsSource="{Binding Source={StaticResource SortedItems}}"
ItemTemplate="{Binding ItemTemplate, ElementName=Selector}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
Grid.Row="1"
Grid.ColumnSpan="3">
I also had the same issue, and eventually I found out the problem is with the data source, and I suspect that your issue is the same as mine.
While CollectionViewSource can work with a number of different types of data sources, not all of them will work with live sorting. To ensure everything work smoothly, it is best to use an ObservableCollection of items that implement INotifyPropertyChanged for the data source.
But if you have to use a custom collection class instead of ObservableCollection, then make sure that class implements IList, not just the generic IList<>. If you don't, live sorting will most likely be disabled. And to ensure all other areas work smoothly, I strongly advise you to also implement INotifyCollectionChanged and INotifyPropertyChanged for it as well.
No matter which collection class you use, the items contained in it still have to implement INotifyPropertyChanged. There are no other ways around it.
In your ItemTemplate, are you binding bool properties to the Checkbox.IsChecked properties? If you are, then you should be able to set that property as the SortDescription.PropertyName property as it seems that you are doing. If not, then that is what you need to do.
I'm trying to create a CollectionViewSource in XAML from an ICollectionView CurrentItem's Property (related table 1..Many), but I got this error:
'System.Windows.Data.BindingListCollectionView' view does not support sorting.
In my VM I have the ICollectionView, wich is the UserControls's DataContext.
public ICollectionView Clients
Client has Loans property, this is what I'd like to bind to a listbox.
It works if I just bind to the CurrentItem's property :
ItemsSource="{Binding Clients/Loans}"
But my problem is the sorting. I want to sort the loans by a property, so I tried to create a CollectionViewSource from that list, but then I got the error above.
<Grid.Resources>
<CollectionViewSource Source="{Binding Clients/Loans}" x:Key="loan_cv">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="CreatedDate" Direction="Descending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Grid.Resources>
Is this possible in XAML without creating a new property in VM ?
If someone else has the same problem, I just created an IEnumerable<> object in VM wich can be ordered. And every time when the CurrentItem property changes on the collectionViewSource, I reset the IEnumerable<> object. It works fine, but some time with large objects, it could be slow..
I am new to MVVM, I have a checkedlistbox in a view with the list of titles(have bound the exposed property in ViewModel to this checkedlistbox control)...
Here is my XAML code that populates the ListCheckBox -
<ListBox x:Name="lstCode" ItemsSource="{Binding Code,Mode=TwoWay}" Grid.Row="1" Style="{StaticResource ListBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="chkBox" IsChecked="{Binding IsChecked,Mode=TwoWay}" Content="{Binding Code_Name}" Margin="0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This control shows the correct list of items with checkboxes for each item in the listbox...
What should be the code in viewmodel to make it work in two way - while getting the codes from database, it should automatically selected the code from the listcheckedbox and when the user selects one or more codes, the viewmodel should be able to know the items selected...
In general, for TwoWay binding, you will need to implement the INotifyPropertyChanged interface on the ViewModel you want to bind to.
In this case, your ViewModel will have to provide a property that returns a collection that your view can bind to, e.g. an ObservableCollection.
This ObservableCollection already allows you to add, update, and delete items in that list in a way that automatically communicates the changes between View and ViewModel.
For the rest I suggest to start digging into MVVM depths. To fully take advantage of WPF's capabilities, you will need to understand the basics for yourself. A great starting point is this SO thread: MVVM: Tutorial from start to finish?
What is the difference between:
<DataGrid
ItemsSource="{Binding MyCollection}"
/>
and...
<CollectionViewSource x:Key="CollectionData" Source="{Binding MyCollection}"/>
...
<DataGrid
DataContext="{StaticResource CollectionData}"
ItemsSource="{Binding}"
/>
They both seem to work. The only difference is that the second snippet, I can't bind to the SelectedItem. So why would someone pick one strategy over the other? Why wouldn't someone just use the first snippet? Thanks.
MSDN states...
CollectionViewSource has a View
property that holds the actual view
and a Source property that holds the
source collection.
CollectionViewSource seperates the actual collection from the view that is representing the collection. This give you the ability to change the visual structure of the visible collection (think filtering out certain items as you type) without actually changing the underlying collection. It is a wrapper around the actual collection containing the objects needing a visual representation. Bea has a great article about it.
In addition you'll notice the explicit wrapping taking place in the CollectionViewSource in your second example...
Source="{Binding MyCollection}"
Then the CollectionViewCource is now being bound to via the DataGrid providing the seperation I mentioned earlier; whereas the collection was being bound to directly in your first example.
A CollectionViewSource has more features that an ObservableCollection or whatever IEnumerable you use for your ItemsSource. For example, it has SortDescriptions that can allow you to group data. An example can be found here.
TLDR; its a more powerful data structure.
As an aside, provided IsSynchronizedWithCurrentItem is true on the DataGrid, you can bind to the SelectedItem by appending a slash i.e. {Binding /}
I have a databound Silverlight DataGrid control that I am trying to sort. I am using RIA services (beta) for my data source, if that makes any difference.
I am quite new to databinding in Silverlight, so this might be something really obvious that I've missed, but I can't seem to find any info on it. I want to be able to set the binding of the ItemSource to a collection in xaml using binding syntax, and have it sorted on one column.
I realize I could set the ItemsSource in code and use LINQ to .OrderBy(). But I don't get a binding that way. It seems like there should be a simple way to do this but I can't find one. How can I keep the binding yet order my collection?
have a look at using a CollectionViewSource. You basically use one as a 'middleman' between your actual collection of data and you data-bound control.
rough example:
<Window.Resources>
<CollectionViewSource
Source="{Binding <<<bind to your collection here >>> }"
x:Key="myDataView" />
</Window.Resources>
...
<ListBox Name="lsyFoo"
ItemsSource="{Binding Source={StaticResource myDataView}}">
...
then in your code behind:
myDataView.SortDescriptions.Add(
new SortDescription("<<<insert property to sort by>>>", ListSortDirection.Ascending));
(ps. you can also add grouping using PropertyGroupDescription)
As you are using RIA Services, you can use the DomainDataSource in your XAML. This will allow you to add SortDescriptors which will do your ordering. See my example below:
<riaControls:DomainDataSource.SortDescriptors>
<riaData:SortDescriptor Direction="Ascending"
PropertyPath="Name" />
</riaControls:DomainDataSource.SortDescriptors>