This is for a Windows 8.1 Store app using .Net 4.5
I found myself replicating the same code for each "object" that I have. So I'm trying to create a more generic method to get all the data the way I want. Originally everything was <Typed> to my different objects but now I'm trying to use the generic <Object>.
public async Task<ObservableCollection<object>>selectAll()
{
var Items = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<object>));
ObservableCollection<object> ItemsList = new ObservableCollection<object>();
if (typeof(Int32) == Items.GetType())
{
//Not Needed anymore
}
else
{
ItemsList = (ObservableCollection<object>)Items;
}
_list.Clear();
foreach (object item in ItemsList)
{
_list.Add(item);
}
return _list;
}
I have my original collection _frequencyList and now a new generic collection _list:
private ObservableCollection<win8Chores.Model.databaseTables.Frequency> _frequencyList;
public ObservableCollection<Object> _list = new ObservableCollection<Object>();
I'm trying to call my new method like this:
_frequencyList = await selectAll();
However, I'm getting an error:
Cannot implicitly convert type
'System.Collections.ObjectModel.ObservableCollection' to
'System.Collections.ObjectModel>observableCollection'
What do I need to do to get this code to work? Am I even on the right track? Any help is appreciated.
Update:
These are the original methods I was trying to refactor for the generic example:
public async Task<ObservableCollection<Person>> selectAllPersons()
{
var personItems = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<Person>));
ObservableCollection<Person> personItemsList = new ObservableCollection<Person>();
if (typeof(Int32) == personItems.GetType())
{
//Not Needed anymore
}
else
{
personItemsList = (ObservableCollection<Person>)personItems;
}
_personList.Clear();
foreach (Person item in personItemsList)
{
_personList.Add(item);
}
return _personList;
}
public async Task<ObservableCollection<Frequency>> selectAllFrequencies()
{
var frequencyItems = await Win8StorageHelper.LoadData("frequency.dat", typeof(ObservableCollection<Frequency>));
ObservableCollection<Frequency> frequencyItemsList = new ObservableCollection<Frequency>();
if (typeof(Int32) == frequencyItems.GetType())
{
//Not Needed anymore
}
else
{
frequencyItemsList = (ObservableCollection<Frequency>)frequencyItems;
}
_frequencyList.Clear();
foreach (Frequency item in frequencyItemsList)
{
_frequencyList.Add(item);
}
return _frequencyList;
}
public async Task<ObservableCollection<Chore>> selectAllChores()
{
var choreItems = await Win8StorageHelper.LoadData("chore.dat", typeof(ObservableCollection<Chore>));
ObservableCollection<Chore> choreItemsList = new ObservableCollection<Chore>();
if (typeof(Int32) == choreItems.GetType())
{
//Not Needed anymore
}
else
{
choreItemsList = (ObservableCollection<Chore>)choreItems;
}
_choreList.Clear();
foreach (Chore item in choreItemsList)
{
_choreList.Add(item);
}
return _choreList;
}
I think you should be using generics for this; see Introduction to C# Generics
public async Task<ObservableCollection<T1>> selectAll<T1>(string filename)
{
var Items = await Win8StorageHelper.LoadData(filename, typeof(ObservableCollection<T1>));
if (Items is ObservableCollection<T1>)
{
return ((ObservableCollection<T1>)Items).ToList();
}
else
{
// empty or not the right type; depending on what the storage helper gives us
return new ObservableCollection<T1>();
}
}
called by
var personList = selectAll<Person>("person.dat");
var frequencyList = selectAll<Person>("frequency.dat");
You need something like this
public async Task<ObservableCollection<T>> selectAllItems<T>(ObservableCollection<T> _list)
{
var items = await Win8StorageHelper.LoadData(string.Format("{0}.dat",typeof(T).Name.ToLower()), typeof(ObservableCollection<T>));
_list.Clear();
if(!(items is ObservableCollection<T>))
{
return _list;
}
ObservableCollection<T> itemsList = (ObservableCollection<T>)items;
foreach (T item in itemsList)
{
_list.Add(item);
}
return _list;
}
_list is the parameter where you need to add all the items.
Then call it like
selectAllItems(_personList);
selectAllItems(_frequencyList); //etc
Related
I tried in either of the ways to bind 2 list views using MVVVM but, couldn't able to do that. While I'm calling 2 property with same API with 2 different models, it is asking me to call await function. But I want both the property to fetch API at a time.
namespace Grading.ViewModel
{
public class GradingViewModel
{
private ObservableCollection<GradingModel> items;
public ObservableCollection<GradingModel> Items
{
get { return items; }
set
{
items = value;
}
}
public GradingViewModel()
{
Items = new ObservableCollection<GradingModel>()
{
};
MyHTTP.GetAllNewsAsync(list =>
{
foreach (GradingModel item in list)
items.Add(item);
});
}
public Details()
{
Items = new ObservableCollection<Details>()
{
};
MyHTTP.GetAllNewsAsync(list =>
{
foreach (Details info in list)
Info.Add(info);
});
}
}
}
If you want to use multiple parallel HTTP calls then you have to use threading
var t1 = //first req
var t2 = //Second reg
await Task.WhenAll(t1, t2);
ApiResponse response1 = t1.Result;
if (response1.IsSuccess)
{
//Success code
}
ApiResponse response2 = t2.Result;
if (response2.IsSuccess)
{
//Success code
}
I have a class which looks like:
private ObservableCollection<string> _areaCollection;
private List<string> _removedAreas;
private List<string> _addedAreas;
public Constructor()
{
_areaCollection = new ObservableCollection<string>();
_areaCollection.CollectionChanged += AreaCollectionChanged;
_removedAreas = new List<string>();
_addedAreas = new List<string>();
}
public IEnumerable<string> Areas { get { return _areaCollection; } }
public IEnumerable<string> AddedAreas
{
get { return _addedAreas; }
}
public IEnumerable<string> RemovedAreas
{
get { return _removedAreas; }
}
public void DisableArea(string areaAlias)
{
if (_areaCollection.Contains(areaAlias))
_areaCollection.Remove(areaAlias);
}
public void EnableArea(string areaAlias)
{
if (!_areaCollection.Contains(areaAlias))
_areaCollection.Add(areaAlias);
}
private void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
var item = e.NewItems.Cast<string>().First();
if (_addedAreas.Contains(item) == false)
{
_addedAreas.Add(item);
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
var item = e.OldItems.Cast<string>().First();
if (_removedAreas.Contains(item) == false)
{
_removedAreas.Add(item);
}
}
}
Then in my controller on a Update actionresult I call a method to update the properties:
private bool UpdateProperties(IUser current, IUser update, out IUser result)
{
result = current;
// Update areas
...
return true;
}
So here I want the following result:
_areaCollection of the result contains the updated list
_removedAreas contains the areas which were removed based on the update
_addedAreas contains the areas which were added based on the update
But I am stuck on this.
I believe you are approaching your problem in the wrong way. From what I understand what you want is to know the differences between two collections. For this purpose you do not need ObservableCollection at all, you just need to filter which elements are removed and which are added.
Assuming current and updated both contains a read/write property called Areas:
var updatedSet = new HashSet<string>(updated.Areas);
var currentSet = new HashSet<string>(current.Areas);
var added = updatedSet.Where(a => !currentSet.Contains(a));
var removed = currentSet.Where(a => !updatedSet.Contains(a));
current.Areas = updated.Areas;
If you really need to keep your Areas property read-only you may change the last line with the following code:
foreach(var item in added)
current.EnableArea(item);
foreach(var item in removed)
current.DisableArea(item);
Which is really inefficient.
I have a situation where I need to store data in list and just pass the relevant fields to my method, how can I do this, please see my code below.
public static List<Supplier_Claim_Upload_Result> ExcludeFailedValidationRecords()
{
IList<CRMSupplierClaimsData> claimsData = GetClaimsUpdateRecordsFromStaging();
using (EmbraceEntities context = new EmbraceEntities())
{
var validatedList = context.Supplier_Claim_Upload(claimsData.LineNunber, claimsData.TotalClaim);// i get an error over here
return new List<Supplier_Claim_Upload_Result>(validatedList);
}
}
Please try with the below code snippet. You got error because you tried to access property from collection in-place of object.
public static List<Supplier_Claim_Upload_Result> ExcludeFailedValidationRecords()
{
IList<CRMSupplierClaimsData> claimsData = GetClaimsUpdateRecordsFromStaging();
List<Supplier_Claim_Upload_Result> lst = new List<Supplier_Claim_Upload_Result>();
using (EmbraceEntities context = new EmbraceEntities())
{
foreach (var item in claimsData)
{
lst.AddRange(context.Supplier_Claim_Upload(item.LineNunber, item.TotalClaim));
}
}
return lst;
}
Update 1:
public static List<Supplier_Claim_Upload_Result> ExcludeFailedValidationRecords()
{
IList<CRMSupplierClaimsData> claimsData = GetClaimsUpdateRecordsFromStaging();
List<Supplier_Claim_Upload_Result> lst = new List<Supplier_Claim_Upload_Result>();
using (EmbraceEntities context = new EmbraceEntities())
{
foreach (var item in claimsData)
{
var test = context.Supplier_Claim_Upload(item.LineNunber, item.TotalClaim);
lst.AddRange(test.ToList<Supplier_Claim_Upload_Result>());
}
}
return lst;
}
Update 2:
public static List<Supplier_Claim_Upload_Result> ExcludeFailedValidationRecords()
{
IList<CRMSupplierClaimsData> claimsData = GetClaimsUpdateRecordsFromStaging();
List<Supplier_Claim_Upload_Result> lst = new List<Supplier_Claim_Upload_Result>();
using (EmbraceEntities context = new EmbraceEntities())
{
foreach (var item in claimsData)
{
var test = context.Supplier_Claim_Upload(item.LineNunber, item.TotalClaim);
foreach (var childitem in test)
{
lst.Add(childitem);
}
}
}
return lst;
}
Let me know if any concern.
Is it possible to convert IEnumerable to a Custom Class that is inherting from ObservableCollection class?
Reason is I want to select only a filtered set of items on the get. I want to implement it on the get because lots of other properties reference CustomItems and perform processes on the items, but I want to somehow make it process filtered set of items depending if a value is enabled or not.
Below is code to help explain what I want to achieve:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public ListView ListView { get; set; }
public void ScrollToItem(object item = null)
{
//Some custom Code
}
}
And here is my property that I want to customize:
private CustomItemsCollection _CustomItems = null;
[JsonProperty]
public CustomItemsCollection CustomItems
{
get
{
if (_CustomItems != null)
{
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
return _CustomItems;
}
_CustomItems = new CustomItemsCollection();
_CustomItemsChangedSource = new CollectionChangedWeakEventSource();
_CustomItemsChangedSource.SetEventSource(_CustomItems);
_CustomItemsChangedSource.CollectionChanged += _CustomItemsChangedSource_CollectionChanged;
return _CustomItems;
}
set { _CustomItems = value; RaisePropertyChanged("CustomItems"); }
}
Specifically, this part:
if(SomeValueIsEnabled)
{
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var castedItems = (CustomItemsCollection)filteredItems;
return castedItems;
}
Is this possible / or maybe wrong? What is the best practice to do it?
Thank you!
You can't just cast it, but you can create an instance of CustomItemsCollection and initialize it with filteredItems.
Add a constructor to your custom class that passes through to the appropriate ObservableCollection constructor:
public class CustomItemsCollection : ObservableCollection<ItemViewModel>
{
public CustomItemsCollection(IEnumerable<ItemViewModel> items)
: base(items) { }
// your other code here
}
Then you can do this:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue));
var collection = new CustomItemsCollection(filteredItems);
return collection;
Try with this code:
var filteredItems = _CustomItems.Where(c => c.Property.equals(SomeValue))
.Select(pre=> new ItemViewModel(){
//add info here
});
var castedItems = new CustomItemsCollection(filteredItems);
My question is that is it possible to create a list that sorts the objects in it upon these object being placed in them?
After not getting anywhere, I made a new linked list. The only task is to make this list ordered by the string field of the objects it will containt while remaining foreachable.
I have the following code:
class LancoltLista<T> : IEnumerable
{
class ListaElem
{
public T tartalom;
public ListaElem kovetkezo;
}
ListaElem fej;
public void ElejereBeszuras(T elem)
{
ListaElem uj = new ListaElem();
uj.tartalom = elem;
uj.kovetkezo = fej;
fej = uj;
}
public void VegereBeszuras(T elem)
{
if (fej == null)
{
ElejereBeszuras(elem);
}
else
{
ListaElem e = fej;
while (e.kovetkezo != null)
{
e = e.kovetkezo;
}
ListaElem uj = new ListaElem();
uj.tartalom = elem;
e.kovetkezo = uj;
}
}
public IEnumerator GetEnumerator()
{
return new ListaBejaro(fej);
}
class ListaBejaro : IEnumerator<T>
{
ListaElem elso, jelenlegi;
public ListaBejaro(ListaElem elso)
{
this.elso = elso;
jelenlegi = null;
}
public bool MoveNext()
{
if (jelenlegi == null)
{
jelenlegi = elso;
}
else
{
jelenlegi = jelenlegi.kovetkezo;
}
return jelenlegi != null;
}
public void Reset()
{
jelenlegi = null;
}
object IEnumerator.Current
{
get { return this.jelenlegi.tartalom; }
}
public T Current
{
get { return this.jelenlegi.tartalom; }
}
public void Dispose()
{
elso = null;
jelenlegi = null;
}
}
}
The problem here is that I'm not able to compare p.kulcs and kulcs.
For real world applications you could use the built-in SortedList<T>.
For your homework, you will have to check every item that you get in your add method against the entire list and insert it into the correct place: between the last element that it's grater than or equal to, and the first element that it's smaller then.
Of course, if the list is empty, or if there is no element greater than the one you add, then you simply append the element to the last available location.
Since this is homework, I'll leave you to write the code yourself.