Example
I have
ObservableCollection<Employee> // 1
ObservableCollection<Boss>// 2
ObservableCollection<Department> //3
ObservableCollection<T> // main >>>I want 1, 2, 3 ObservableCollection to main ObservableCollection
How to do?
edited1: I want to add them to be a list. Not for each item.
edited2: I have to display 3 lists of field on the wpf application. the 2nd list can add/remove item in the list.
** please let me know if it unclear.
Since what you want to do is to add a collection to a collection, but those collection types are not compatible, I'd try this
ObservableCollection<Employee> _employees = ...
ObservableCollection<Boss> _bosses = ...
ObservableCollection<Department> _departments = ...
ObservableCollection<IList> _collections = ...
_collections.Add(_employees);
_collections.Add(_bosses);
_collections.Add(_departments);
Note that the generic argument to the _collections collection is IList. ObservableCollection<T> implements IList and is therefore assignable to things of that type, even for different Ts among the sets.
Observable Collection does not support something like AddRange functionality where in you can add your entire list to an already existing list.
By the way, if all your observable collection is of type T, you could use foreach to iterate through and do the adding, something like below:
var observableCollection1 = new ObservableCollection<string>();
var observableCollection = new ObservableCollection<string>();
foreach (var element in observableCollection1)
{
observableCollection.Add(element);
}
But, what you are trying to do, as from my understanding, is trying to add an observable collection of type department to a different type T, which is not possible unless you try to add it to an observable collection of simply, objects. Warning: Note, you might need to box/unbox afterwards.
Code Snippet:
var observableCollection_Department = new ObservableCollection<Department>();
var observableCollection_Employee = new ObservableCollection<Employee>();
var observableCollection_Boss = new ObservableCollection<Boss>();
var observableCollection = new ObservableCollection<object>();
foreach (var element in observableCollection_Department)
{
observableCollection.Add(element);
}
foreach (var element in observableCollection_Employee)
{
observableCollection.Add(element);
}
foreach (var element in observableCollection_Boss)
{
observableCollection.Add(element);
}
Related
I have a list that is bound to a datagrid, a property of the items is a boolean and is bound to a checkbox in the datagrid.
How can I allow only one checkbox to be selected?
For example, if one checkbox is selected, then the other checkboxes should be unselected.
What I have tried so far (in the ViewModel, Update is the boolean property):
var update = item.Update;
Items.ForEach(x => x.Update = false);
Items = new List<Item>(Items);
item.Update = update;
But this not efficient and it throws an Exception that the list was modified (collection was modified; enumeration operation may not execute).
Is there an efficient way to get the job done?
Edit: I'm using Binding to bind the list, the list is from type List<>, and the items of the list implement INotifyPropertyChanged
I've commented the issue that you have in this code:
var update = item.Update;
Items.ForEach(x => x.Update = false);
Items = new List<Item>(Items); //This creates a new, empty Items list
item.Update = update; //this item relates to an item in the collection that no longer exists
You should have ObservableCollection<Items> Items so that if you add/remove items from your list the Binding will follow and Item implementing INotifyPropertyChanged. As ObservableCollection doesn't support ForEach your code becomes:
var update = item.Update;
foreach(var element in Items)
{
element.Update=false;
}
item.Update = update;
Is there any way that I can have multiple views on a single Observable Collection, with different filters, that I can Refresh?
I have an Observable Collection called Proficiencies. I have three list boxes, each should display a subset of the Proficiencies items, filtered on a value within the Proficiencies items. i.e. One list displays items of category A, one list displays items of category B & one list displays items of category C.
I am trying to filter the collection using CollectionViewSources (called the SkillsView, ToolsView, and LanguagesView, one for each list box, each with it's own filter. They are properties in my ViewModel class that the lists boxes Bind to. they are declared in the form of:
protected ICollectionView theSkillsView;
public ICollectionView SkillsView
{
get { return theSkillsView; }
protected set
{
theSkillsView = value;
OnPropertyChanged("SkillsView");
}
}
I have two ways of initialising them either (1):
theSkillsView = new CollectionViewSource { Source = Proficiencies }.View;
theToolsView = new CollectionViewSource { Source = Proficiencies }.View;
theLanguagesView = new CollectionViewSource { Source = Proficiencies }.View;
Or an alternative Ive found (2):
theSkillsView = CollectionViewSource.GetDefaultView(Proficiencies);
theToolsView = CollectionViewSource.GetDefaultView(Proficiencies);
theLanguagesView = CollectionViewSource.GetDefaultView(Proficiencies);
I then Apply the Filtering:
theLanguagesView.Filter = p => ((ProficiencyData) p).Category == ProficiencyCategoryType.Language;
theSkillsView.Filter = p => ((ProficiencyData) p).Category == ProficiencyCategoryType.Skill;
theToolsView.Filter = p => ((ProficiencyData) p).Category == ProficiencyCategoryType.Tool;
The problem is:
if I use Option (1) all the views have the same filter (which ever is applied last)
If I use option (2) when I call Refresh() I get the following error:
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=PresentationFramework
StackTrace:
at System.Windows.Data.ListCollectionView.PrepareLocalArray()
I could create three seperate Collections, but that a) means I don't have all the items in a single collection and b) seems to be not in the spirit of things when CollectionViewSources are available precisely for Sorting, grouping and Filtering.
Many thanks in advance for any suggestions.
You should create three separate views of the AllItemsInDataBase source collection:
theSkillsView = new ListCollectionView(AllItemsInDataBase);
theToolsView = new ListCollectionView(AllItemsInDataBase);
theLanguagesView = new ListCollectionView(AllItemsInDataBase);
You can then filter the views independently of each other.
So i have an object of ojects like so
[["value1","value2","value3"]]
and my goal is to access these objects, and modify them, then return it to a new list containing the existing objects.
Here's what I've tried
List<dynamic> data = new List<dynamic>();
foreach(var i in objects)
{
List<dynamic> innerData = new List<dynamic>();
foreach(var j in i)
{
innerData.Add(j + " NEW");
}
data.AddRange(innerData);
}
the output isn't the same. It will return the following
[["value1 NEW"], ["value2 NEW"],["value3 NEW"]]
It returns a new list, but instead of having one object with three values inside the list, it returns three objects with one value inside the list.
My goal is to have the same output format as the input format. Like so
[["value1 NEW","value2 NEW", "value3 NEW"]]
As already suggested in the comments you need to use Add instead of AddRange. AddRange adds each element of a list as a new element in the outer list and what you want is add the inner list as one element of the outer list.
The fixed code then looks like this:
List<dynamic> data = new List<dynamic>();
foreach(var i in objects)
{
List<dynamic> innerData = new List<dynamic>();
foreach(var j in i)
{
innerData.Add(j + " NEW");
}
data.Add(innerData);
}
I am using List of Lists in my project. When i run program i get ArgumentOutOfRangeException. But there is no range specified in list.
I declared list like this:
public static List<List<string>> list = new List<List<string>>();
Now i want to add my name in the first "list" which is in the List of lists.
list[0].Add("Hussam"); //Here i get ArgumentOutOfRange Exception.
What should I do now?
But there is no range specified in list
No, there's an index specified (as an argument), and that's what's out of range. Look at your code:
list[0].Add("Hussam");
That's trying to use the first list in list - but is list is empty, there is no first element. The range of valid arguments to the indexer is empty, basically.
So first you want:
list.Add(new List<string>());
Now list[0] will correctly refer to your empty List<string>, so you can add "Hussam" to it.
You want to add an item to the first item in an empty list... That isn't going to work. First, add the list inside the other list:
public static List<List<string>> list = new List<List<string>>();
List<string> innerList = new List<string>();
list.Add(innerList);
innerList.Add("Hussam");
Why are you creating a list of a list? Wouldn't List suffice? What is happening here is the inner list is not being initialized.
list.Add(new List<string>());
list[0].Add("Jimmy");
In this case ocurred an exception because you tried acess an index which not exists, then you must add an inner initial list, which could be done follows:
list.Add(new new List<string>());
Or, if you want add an first name directly:
list.Add(new new List<string>(){"Hussam"});
Ok so first, you have to understand that the "index" only comes after the value has been declared. Lists behave different. They are not like arrays. You get the index in which you want to store the item and when you do that, you use the code array[index] = value;.
But in a List, to give a value to a completely new item, you use the method Add(value).
So here's a reminder: Systems.Collections.Generic.List<> has nothing to do with array[ ]s
You cannot access list[0] as there is no item at index 0. The list is empty.
You need to add a new List like this:
list.Add(new List<string> { "Hussam" });
or, assign a list to index 0 and then add to it as per your posted code:
list.Add(new List<string>());
list[0].Add("Hussam");
If you don't always know if the list will be be empty or not you can use FirstOrDefault (a LINQ method) to check if there is any entry at index 0 and assign one if not, otherwise use the existing inner list:
var innerList = list.FirstOrDefault();
if (innerList == null)
{
innerList = new List<string>();
list.Add(innerList);
}
innerList.Add("Hussam");
The problem is, your nested list hasn't been initialized, with anything.
So, calling the first item of the nested list is correctly telling you there is nothing in it.
To verify:
int superlistCounter = 1;
int sublistCounter = 1;
foreach(var sublist in list)
{
Console.WriteLine("Now in List #" + superlistCounter);
foreach(var item in sublist)
{
Console.WriteLine("List item #" + sublistCounter + ": " + item)
}
}
The output will be:
Now in List #1
It sounds like you're expecting:
Now in List #1
List Item #1: Hussam
To fix this, simply initialize your list!
public static List<List<string>> list = new List<List<string>>();
// ...
List<string> subList1 = new List<string>();
list.Add(subList1);
subList1.Add("Hussam");
I am trying to remove selected items in a ListBox which is bound to ObservableCollection.
var selectedFiles = MyList.SelectedItems;
foreach (cListEntry item in selectedFiles)
{
_myList.Remove(item);
}
"Collection was modified; enumeration operation may not execute"
What is the proper way of doing this?
You can't modify the collection while enumerating it as evident from the exception itself.
Explanation:
When you remove item from ObservableCollection, MyList.SelectedItems gets update since ObservableCollecton implement INotifyCollectionChanged.
Now, selectedFiles is pointing to same reference which results in modifying it.
Solution
Instead create a new list and enumerate over that so that any change in ObservableCollection doesn't reflect back to list which you are enumerating. This will work:
var selectedFiles = MyList.SelectedItems.Cast<object>().ToList();
foreach (cListEntry item in selectedFiles)
{
_myList.Remove(item);
}
This happens when trying to modify an ObservableCollection<T> that is bound to a ListBox, for example. This is how you deal with that:
ObservableCollection<Employee> itemsToRemove = new ObservableCollection<Employee>();
foreach (Employee item in lsbxNames.SelectedItems)
{
itemsToRemove.Add(item);
}
foreach (Employee item in itemsToRemove)
{
((ObservableCollection<Employee>)lsbxNames.ItemsSource).Remove(item);
}
Create a new ObservableCollection<T> called itemsToRemove, with the same T as your collection you are trying to modify.
Iterate through your nodes of SelectedItems in your ListBox. Add them to itemsToRemove.
Iterate through itemsToRemove. Cast the ListBox ItemsSource to an ObservableCollection<T> and remove the matches in itemsToRemove from it.
Reference: http://docs.telerik.com/devtools/wpf/controls/radgridview/managing-data/deleting-entry
So this would mean you should be able to do this:
ObservableCollection<cListEntry> itemsToRemove = new ObservableCollection<cListEntry>();
foreach (cListEntry item in MyList.SelectedItems)
{
itemsToRemove.Add(item);
}
foreach (cListEntry item in itemsToRemove)
{
((ObservableCollection<cListEntry>)MyList.ItemsSource).Remove(item);
}
I'm not sure what _myList is, but you don't need to modify it. Just go directly to the ListBox.