I'm using ObservableCollection<T> to bind some data to some view.
While I'm editing DB existing data, I can save data edits by calling only a single Savechanges() method in my view model, also add new items to collection and I can edit them, but the SaveChanges() method doesn't insert additional rows to db.
I don't know what entities are passed to the viewmodel. The T is a merged class of multiple entities so I have to do this.
In Constructor:
collection=globalContext.TSet;
//the collection and context are defined in class level
Code to get a new item:
collection.Add(New T());
CurrentItem=collection.Last();
where collection is the ObservableCollection<T> and CurrentItem is the currently editing item.
EDIT:
The context.ChangeTracker.Entries doesn't recognise the new object.
I have a complex type(say T) which is the result of some join query,I have no idea that T is creating from which entities so I can not get the Entity => I can not say the context that what type of Entity I want to add.
So I have to force change tracker to create the new object from complex type which is the result of some join query.
I'm using EF4.3.1
Any suggestions?
Thank you.
The database is not getting updated. Modify the DBSets in the view (or view model) via IDbSet, then issue a DbContext.SaveChanges Do this instead of directly modifying the ObservableCollection. The ObservableCollection should then refresh itself and update the view model and view. If it does not requery the database to generate a new DbSet then get a new ObservableCollection from DbSet.Local for the view model then create a new view from that.
You haven't added the new entity to TSet. You need to call TSet.Add(t) or hook up the CollectionChanged event of the ObservableCollection to do it automatically.
Related
I have a ViewModel with some ObservableCollection _questions, which is loaded from DB when VM instance created. Also this list is used to collect data to save back to DB.
This Vm is used for a View1 and it displays the list in ListView with filtering by a property using CollectionViewSource.GetDefaultView(_questions).Filter = ...
Now I need to create View2 which will display same list but without filtering.
I can't bind it to the same ObservableCollection _questions because it has filter defined on CollectionViewSource, but I need to use it to keep SaveToDb code same.
Is it possible to have different filtering on the same data source for two different ListViews?
I have never enjoyed using CollectionViewSource. I would instead filter using a new property in my ViewModel that filters using Linq:
public IEnumerable<MyType> FilteredItems()
{
get
{
return MyCollection.Where(x => x.MyProperty == SomeValue).ToArray;
}
}
I would then bind ItemsSource to this property and use INotifyPropertyChanged event to notify UI of changes to the collection.
Its hard to tell if this fits your scenario well as there is not much information provided on what you need to achieve.
I am having a bit of trouble understanding the correct way to do the following:
The data I am binding to exists on the internet as a json file. On a timer tick, I download it and using a JavaScriptSerializer, I deserialize it into a class.
Now, I want to bind to that data but when I deserialize, it creates a new class, so my binding breaks (meaning I have to set the ItemsSource or DataContext again).
Does anyone know a way around this?
Thanks!
What is the control that you are trying to bind your data to? If you can bind an observable collection as your data source, all you need to do is to clear your observable collection before fetching the data, and just add the fetched record to the collection post deserialization.
If you do not use ObservableCollection, you can add public properties to your ViewModel and just refresh those when you get the data back. This will ensure the refresh happens becuase your view is bound to public properties of your view model and not aware of the object returned from the call.
After binding deserialized data you should call PropertyChange event of the property you want rebind. In case the selected value is in the new (deserialized) collection it should be reselected.
After spending a whole day trying different suggestions, I'm back at square 1. I'm trying to bind my view, a XAML Window, to one of my ViewModel properties, say, SalesOrders. The ViewModel in turn talks to the Model (an EF Model on top of a database). The question I'm facing is the collection type that I should use to expose my SalesOrders property.
I have tried the following types, none of which does all of what I need.
List<T>
ObservableCollection<T>
BindingList<T>
CollectionViewSource on top of the above
Here's what I need my collection to do:
The view has Previous/Next buttons, so the collection should provide some sort of currency manager.
There's a Save button in the view, which I need to get enabled/disabled immediately based on whether the SalesOrder collection has any changes. Since SalesOrder is already an EF type, all of its fields implement INotifyPropertyChanged.
CollectionViewSource provides me with navigation methods (previous/next) but doesn't listen to PropertyChanged events, so modifying data in the view doesn't turn the Save button on. BindingList can listen to PropertyChanged events, but doesn't provide navigation methods. ObservableCollection lacks both functionalities.
TIA.
Why don't you use ObservableCollection<T> then subscribe to the CollectionChanged event to enable or disable your save button as outlined in the answer of the thread MVVM ObservableCollection Bind TwoWay.
According to MSDN about CollectionView here:
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.
Which means you can use BindingList for SalesOrders and bind it in the View, then to manage the navigation you can access its automatically created CollectionView from the ViewModel with:
myCollectionView = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this.SalesOrders);
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
I have a datagrid which has its ItemsSource bound to the result of a linq query (.ToList())
I can make changes to properties of the collection bound to the itemssource, and these changes are reflected immediately in the datagrid fields, such as;
myQueryList[2].myProperty = newValue
What I can't do though, is see the changes made in the database reflected in the datagrid by this;
myQueryList.Refresh(RefreshMode.OverwriteCurrentValues, myQueryList[2])
I have inspected the value of myQueryList[2].myProperty after this refresh, and it shows it has correctly updated from the database. Why does the datagrid not display it, and how can i get the datagrid to display it?
Also; I have found the same problem with using an ObservableCollection
Thanks to Casey's (edited) response in this post, i've found a workaround
I've implemented the SendPropertiesChanged() on the collection members and call it whenever i do a Refresh()
Once you convert a query (deffered/dynamic) to a collection (fixed) using ToList() method, a separate collection is created. This new collection has no connection to the query. When something changes in query, it does not reflect on collection. You will need to reset the ItemsSource property whenever you call Refresh() on query.