How to copy data from ObservableCollection with conditions? - c#

I want a copy of an ObservableCollection by filtering it with some condition. Please help me.
I treid the following code:
ObservableCollection<YourEntity> clonedCollection = new ObservableCollection<YourEntity>(clonedList);
This is ok, but need copy with condition (new object filtered from the old one). need to copy some particular data from clonedList

Use a linq query to filer the elements in the source collection.
A .Where() query does it pretty good. You can use .Select() or any other query too.
ObservableCollection<YourEntity> cloned = new ObservableCollection<YourEntity>(source.Where(e => e.IsSomeConditionFulfilled()));
Note that you do not clone the objects passing an IEnumerable to the constructor of the ObservableCollection - both collections cloned and source will reference the same objects. That means, if you change some YourEntity instance properties via the source collection (e. g. source.First().SomeProperty = SomeValue), and this object is also contained in the cloned collection (e. g. cloned.First() == source.First()), then those changes will be reflected there.

Related

Modifying a List of Objects through a List of Wrappers

My goal here is to retrieve a List from a class instance and then modify the objects within that list, however I do not know how the objects will be affected and need some valuable knowledge.
Let's say we have two cases:
Create a new List which gets the list from the class instance:
List<SomeType> ItemsList {get { return classInstance.ItemsList;} set {...
Create a new List of wrappers, each item in the list contains the original object with some additional properties:
List<SomeType> itemsList = classInstance.ItemsList;
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x, IsSelected = ...
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
I will be using multiple ObservableCollections in multiple DataGrids, I have used Lists in this example simplify the situation but I'm sure the result would be the same.
Edit:
I realize the Title does not describe my problem well, I encourage anyone to help me improve it.
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
Yes, unless you create a copy SomeType and add the copy to the new collection.
The following creates a new Wrapper objects for each SomeType object...
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x } );
...but each Wrapper object still has a reference (though the Item property) to the same SomeType object that's in classInstance.ItemsList.
When the properties of SomeType (mutable reference type) instances are changed via Wrapper then the objects in the original list change, because they are the same objects.
When the list holding Wrapper objects changes (you move, add or remove objects) the the original list is not affected.
When original list is changed (you move, add or remove objects) the list containing Wrappers is not affected.
To synchronise the collections, you should use ObservableCollection for original list and implement collection (probably also ObservableCollection-derived) for Wrappers that auto-updates itself when source collection changes.

EF objects behaviour

Whenever i am changing an Entity Object reference changes are reflected to all other previous Objects that point to the same Entity. example:
var menu = menuRepo.FindByByIdAsync(12);
var menu1 = menuRepo.FindByByIdAsync(12);
menu.Name = "Name";
Console.WriteLine(menu.Name+ " "+ menu1.Name);
At this point if i run the code snippet both menu and menu1 are changed.
Is this happening because of the Entity's Proxies? I dont really understand it. If those two Objects where Class Objects they would have different names...how is this possible?
EDIT
Even stranger is the Orderby scenario i have tried...
var menu = menuRepo.FindById(1);
menu.MenuItems.OrderBy(m => m.OrderField).ToList();
these 2 lines actually order the items collection inside the menu Object.
I dont even have to set them...???
menu.MenuItems = menu.MenuItems.OrderBy(m => m.OrderField).ToList();
EF keeps only one instance of the same object in its context; FindByIdAsync retrieve the item having Id = 12 and set a reference of it in the context. The second time you call FindByIdAsync it returns a reference from the context to the same object. So that is why when you change the property in the first object the corresponding property in the second object is changed as well.
OrderBy dosen't return the ordered collection itself; the returned value is an object that stores all the information that is required to perform the sort.
The sorting is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach.
menu.MenuItems.OrderBy(m => m.OrderField)
dosen't execute any sort
menu.MenuItems.OrderBy(m => m.OrderField).ToList();
execute the sort because ToList() is invoked

filtering a List before binding to a DataGridView

I have created a class which has three attributes. I created a List collection of that object.
I've used that collection for filling a DataGridView. I want to filter the data from the DataGridView.
How can I filter the list collection?
You can use generic function for it like..
List= List.FindAll(delegate(class obj)
{
return obj.name=="abc";
});
Here "obj" is a object of your class and the "name" is a property by which we can filter property.
If it is a list collection and you are using .Net 2.0, You don't have the LINQ support. In that case one option would be do the filtering before getting the objects in the list.
i.e. You get the Data from SQL Server into a DataTable and then have multiple Dataviews (1 for each filter). From these views you can populate your list objects.

C# - Using a copy of Session-stored variables instead of reference

I have an asp:ImageButton with OnClick="Btn_OnClick".
In Btn_OnClick I have this line:
DataTable dtTable = (DataTable)Session["someSessionKey"]
and dtTable is altered in the function.
I've noticed that if the button's clicked more than once, the dtTable I take from the session contains the altered table, probably meaning dtTable is not a copy but a reference of the session variable.
How can I alter a copy of Session["someSessionKey"], and not the actual value?
Thanks!
DataTable dtTable = ((DataTable)Session["someSessionKey"]).Copy();
If the object in the Session implements ICloneable, you can use var myCopy = mySessionObject.Clone();. You would then have to read the documentation of the object to see what it exactly does.
This is because there is no generic solution to cloning. Mostly, objects have other non-scalar objects as properties, so it always depends on the scenario if you need to clone those child objects too.
When you author your own class, you can always call the protected MemberwiseClone() method that is defined in System.Object to get a flat clone. You can then choose if you want to add some additional cloning logic and if you want to make it available for callers outside.
If the object in the Session is a List<T> or an IEnumerable<T>, you can do var myCopiedList = new List<T>(myListInSession);. Keep in mind that the individual objects in that list are not cloned in that case. You'd have to foreach through them and clone each object manually. It's similar with the DataTable. You might need to manually create a new instance and copy the content over.
To manually clone an object that doesn't support any public method to do so, you'd have to create a new instance of it. Then you'd assign every property from the original object to the cloned object manually. That can be not only tedious, often it also won't work because there are protected members that you can't access easily.
Finally, you can resort to reflection or other tricks to try to clone an object. A quick google search gave me that result: C# Object clone wars.

How to modify an item in an IEnumerable collection and retain its order

I have the following situation. I have a list of items which have an "Id". I have to search for an item with a specific id, modify its values and maintain the order of the collection. What would be the best way to do that?
var collection = <some_linq_query>
collection.Where(i=>i.Id=someId).FirstOrDefault().Property = "bla";
// now collection should be the same but the item updated.
The call to Where does not modify the original LINQ query stored in collection in any way. Instead it creates a new IEnumerable<T> where is a subset of the original query. The subset will have the same relative ordering as the original set in collection
The only way this could cause a problem is if the value collection is a LINQ where which has a Where clause, or is otherwise filtered, base on the value of Property. If that is the case and you want to preserve the order force collection into a non-lazy evaluated structure via .ToList.
collection = collection.ToList();
As long as the objects in the collection are mutable, your code should work fine.
By the way, FirstOrDefault takes an optional filter parameter, so you can write collection.FirstOrDefault(i => i.Id == someId).

Categories