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
Related
Suppose I have a object ListCollectionView and bind it to a datagrid. I bind the object's Name property to a TextBox(one of the datagrid's column)'s Text property and add my specific ValidationRule.
Now I want to the rule to check if the Name property is duplicated, I need to check other objects in the ListCollectionView, if there are objects' Name property equals to this Name, the validate result will be false.
My question is this check can apply only to the edited object, So only this object will become red when its Name is duplicated, but how can I also make check to other list objects, make the other objects which Name property equals to this edited one also become red? Thanks.
You are correct that the ValidationRule only has access to the data it is bound to. However you can write a custom ValidationRule - I've got a blog post detailing it here, and you can then add extra properties to it so you can inject the appropriate data that your bound value should be checked against.
However you will strike one tricky problem - the cells in the datagrid have no natural access to the DataContext of the datagrid because datagrid columns are not in the visual tree. To get around that problem you can use a static proxy object which contains (binds to) the ListCollectionView, this proxy object can then be bound to by the ValidationRule (example 1, example 2).
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();
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.
I have four entity Customer, product, order and order details. On my WPF window I have customer list box showing customer name and on select of customer I would like to populate the order list box which also in my window.
Since i am using MVVM, I should have two view model, one for customer and another for order, right? and i should pass the customer to orderview model so that it can populate the orderview.
How do I even pass selected customer to the order view model? I have a property named selected item on customer., but I still dont c how shall I get that in my order view model.
Update:
#Craig Trombly I have created the ObservableCollection of my order entity and has property on my view model that is binding to in Xaml. I am implementing master detail behavior like on select of customer populate my order list box. For that i need to have a property on my customer view model and I am binding that property to selectedItem in the list box in my customerView Xaml. i named that property as selectedItem. however whenever i am trying to access that selected item property from orderview model. it is not working. can you plz tell what i am doing wrong? that selectedItem property in my customer view model should set everytime I select a new item in the list on customer view. it s not doing that either.
The ViewModel is tied to your View (the xaml & cs), it is not around the data.
For instance, MainWindow.xaml & cs should have a MainWindowViewModel.cs
You use one ViewModel to your view. I would suggest using the entity framework for your data.
I have a listbox bound to a collection. I would like the ListBox to always reverse the order of the items. This handler--hooked up to the control's load event--works for the initial load, but not thereafter. Ive tried using the SourceUpdated event but that doesnt seem to work.
How do I maintain a constant active sort?
MyList.Items.SortDescriptions.Add(New SortDescription("Content", ListSortDirection.Descending))
How is the collection stored that supplies the items for the ListBox? It should be a collection that supports INotifyCollectionChanged. The framework provides ObservableCollection<T> which you can use.
In the constructor of your ViewModel (or wherever the collection lives), you then get the DefaultView for adding the SortDescription. The CollectionView is like a layer on top of your collection, which you can use to sort, group, filter, etc. the items without actually affecting the underlying data source. The framework creates a default one for you. To get a reference to it, you can use code similar to the following:
var collectionView = CollectionViewSource.GetDefaultView(Widgets);
if(collectionView == null)
return;
collectionView.SortDescriptions.Add(new SortDescription("Content", ListSortDirection.Descending));
With that in place, you should be able to add items to the ObservableCollection<T> and the sort order will be maintained.
If your source collection is a List<T> or some other collection that doesn't implement INotifyCollectionChanged, there is no way WPF can detect when an item is added. You need to use a collection that implements INotifyCollectionChanged, like ObservableCollection<T>.
Also, the items in your collection need to implement INotifyCollectionChanged so that changes to the items are taken into account