Stange removing behavior on observablecollection - c#

I am having a strange behavior while trying to remove an element from the Children Collection. As you can see the first time the remove method gets executed the count is 8 (didn't change) but if I step inside the remove method the element gets removed.
What is going on? (hopefully the code included on the images is enough to get a clue about it, if not please ask for more details)
Edit: I already changed a interface a little bit according to a suggestion given in an answer, but the issue remains. this Also lead to some changes on the implementation (mind the red strikes on the image, sorry for the paint skills).
public interface ITreeContentItem
{
string Name { get; set; }
int Id { get; set; }
int Level { get; }
ITreeContentItem Parent { get; set; }
IEnumerable<ITreeContentItem> Children { get; }
bool ChangeParent(ITreeContentItem parent);
Thickness Border { get; }
}

And the problem was very simple... I was incrementing i twice on my for loop in the remove method.

Your Children property returns a copy of the collection so you are removing an item from the copy and not from the original collection.
Change your code from
get { return new ObservableCollection<ITreeContentItem>(Children); }
to
get { return Children; }

Related

Why does a property called DefaultStringValue always appear first in IntelliSense?

If you define the following class:
public class Test
{
public string Something { get; set; }
public string AnotherThing { get; set; }
public string DefaultStringValue { get; set; }
}
then, when you list the properties with IntelliSense, DefaultStringValue appears first in the list, despite this not being in alphabetical order:
If you change the property name to anything else, normal service is resumed:
Anyone know why this is? I'm curious...
(Note: I'm also using Resharper Ultimate 2018.1.2)
This is IntelliSense (and/or ReSharper) being, well, intelli-gent, and trying to help you re-use things you've used previously. If you start again from nothing, you'll find that things are alphabetical:
I'm betting that at some point in the past, you've made use of the DefaultStringValue property, and not the others, so it's suggesting it first:
Having renamed it, if you enter the line t.DefaultStringValu = "x";, then delete it again, next time you enter t. and invoke IntelliSense, DefaultStringValu will now be top of the list:

Removing an item from a list doesn't remove from the saved object in Entity Framework/MVC

I have an entity that needed a list of type int. Due to this being an internal tool that only I would use, I didn't want to spend a lot of time making a UI/view to edit the list and I sort of cheated.
So, I have the following class:
myitem.cs
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
virtual public ICollection<Size> Sizes {get;set;}
size.cs
public int ID { get; set; }
public int Size { get; set; }
Between the controller and view controller, I did some funky bits. I had a single text field in the view controller called "Sizes" and I then split the input on a comma to an array, and assign the list to Sizes.
This works perfectly and as expected.
string[] sizes = model.sizes.Split(',');
myitem.size = new List<sizes>();
foreach (string item in sizes)
{
myitem.size.Add( new sizes {Size=int.Parse(item)});
}
In the edit one, I find the object, and create a new text string that basically gets all of them and this also works.
In the edit saving controller, no matter what I try, it seems to append. So, I basically did the following:
MyItem myitem = db.myitems.find(id);
...auto mapper stuff from viewmodel to model...
myitem.sizes=null;
...call same bits as create to split and add to sizes...
db.savechanges();
However, I am now finding that whatever I try to do in edit, it simply adds to the list in addition to what is already there - I can't seem to find a way to remove it.
I have tried many different things (instead of = null, foreach and remove(), and a few others) without much luck.
In the end, I don't think this is the best approach at all as I am going to end up dropping the items and recreating them by the thousands for the sake of saving a few minutes, so, I am going to create a DBSet for sizes and do an ajax interface to list/delete/add them separate to the main model. (If there is an easy way, please let me know?!)
However, the fact that this didn't work has annoyed me and I was wondering if anyone knows why?

WPF nested ListBox control does not update the list it is bound to

I have the following two classes (with altered names), that will be used to populate a ListView with a nested Listbox
private class ObjectName //For the Listview
{
public int ID { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public List<BabyObject> Field3 { get; set; }
}
private class BabyObject //For the nested Listbox
{
public string Field1 { get; set; }
public bool Field2 { get; set; }
}
I populate an Observable Collection with some objects and set it as the ItemsSource of my ListView.
My ListView correctly displays the Objects in each ListViewItem, and the nested listbox in each item correctly displays each BabyObject.
The Problem:
If I edit the ID, Field1 or Field2 values using the UI, the Observable Collection in memory also updates - of course it does, because of the binding. However if I edit any of the BabyObject's values, the List in memory doesn't change.
Therefore, when I change the Controltemplate of the ListView (so that values are displayed in labels instead of textboxes), the BabyObject values change back to their original.
I know people often have trouble updating the interface when Lists are updated in code, but not this way round?
I'll be happy to answer questions and include more code but the XAML is rather large. In the meantime I am going to make a separate example listview to see if I can test this on a smaller control.
Thanks
You need to raise a property change notification when the properties are set - this tells the bindings to update.
MSDN docs here
I have solved the problem, however I have no idea what was causing it.
I tried setting the Binding of the Baby Objects to a variety of Modes, and changed the List to an Observable Collection.
This did not work, so I manually undone the changes (Not setting the mode and using a List) - and now it works fine.
If I edit the BabyObject values using the interface, the changes are also made to the List.
I am baffled too - sorry for wasting your time!

Removing Tree Branches with C#

I have a List<Leaf> named items in C#. A Leaf has the following properties:
public class Leaf
{
public int ID { get; set; }
public int ParentID { get; set; }
public bool IsFlagged { get; set; }
}
If a Leaf has the IsFlagged property set then I need to remove it from the collection of items. In addition, I need to remove all of that Leaf entity's children. I'm trying to figure out the most elegant way to write this code. Currently, I have a loop within a loop, but it seems sloppy.
Does anyone know of an elegant way to do this?
Perhaps:
void RemoveItAndChildren(Leaf leaf)
{
foreach (Leaf item in items)
if (item.ParentID == leaf.ID)
RemoveItAndChildren(item);
items.Remove(leaf);
}
And use so:
foreach (Leaf leaf in items)
if (leaf.IsFlagged)
RemoveItAndChildren(leaf);
Note that, as in a comment above, something like the following might be more appropriate:
public class Leaf2
{
List<Leaf2> Children;
bool IsFlagged { get; set; }
}
Most reasonable (and probably "the most elegant") way of dealing with tree is to store it as a tree, not an array/list. In this case you'll not need to deal with walking elements to try to find all children.
Note that depending on your actual requirements tree may not be best data structure, but for removing node with all children nodes it would be hard to beat regular tree.

Custom object referring to itself, how to stop it looping forever?

I have a custom object of School, which is part of a family of schools. So when I return a school, I can return the schools it is linked to in its family.
However, when I do this it manages to loop forever, how can I stop it. Like only going 1 level deep and not becoming recursive?
public class School
{
public long BaseId { get; set; }
public string BaseName { get; set; }
public string SchoolFamily { get; set; }
public List<School> LinkedSchools
{
get
{
var schoolRepository = new SchoolRepository();
return schoolRepository.GetAllSchoolsLinkedByFamily(SchoolFamily).ToList();
}
set { ; }
}
}
Add a Boolean member variable to act as a flag, default cleared. First thing to do in the get function is check that flag. If it is set, return an empty list. Otherwise set the flag, create the list, and clear the flag, then return the list.
You can pass the current instance of your School (this) into the GetAllSchoolsLinkedByFamily and when that reaches the instance you can stop.
Change the LinkedSchools property to be a method that accepts an optional integer parameter of nestLevel. Something like this:
public List<School> GetLinkedSchools(int nestLevel)
{
// Get schools logic here...
}
Then change your code so that each level of recursion increments a counter and returns once the counter is equal to nestLevel.
I would recommend first adding the current school to the return Collection and passing that Collection through each recursive iteration. Then, inside the iteration method, only add / perform a deeper iteration for the schools that are not already in the list. In this way you get all of the related schools but no endless recursion.
Edit: Mark Jones Graph Traversal (marking visited nodes) suggestion below is actually cheaper if you don't mind adorning your class.

Categories