Update list values after update root class object - c#

I have the following classes:
public class Class_A
{
public string my_field { get; set; }
public int id { get; set; }
// etc...
}
public class Class_B
{
public string my_field { get; set; }
public Class_A field_A { get; set; }
// etc...
}
public class Class_C
{
public string my_field { get; set; }
public Class_A field_A { get; set; }
// etc...
}
List<Class_A> list_A = new List<Class_A>(); //and then populate it
List<Class_B> list_B = new List<Class_B>(); //and then populate it
List<Class_C> list_C = new List<Class_C>(); //and then populate it
And then, when I update some element of list_A, for example
Class_A old_a, new_a;
old_a = list_A.Where("some condition").FirstOrDefault();
new_a = new Class_A();//and then initialize it
list_A[list_A.FindIndex(x => x.Equals(old_a))] = new_a;
I need, that all elements of list_B and list_C, which field Class_A equals old_a will be update to new_a.
1. What is the best way to do this? Now I have following variant, but I think, that it's could be better:
list_B.Where(x => x.Class_A.Equals(old_a)).ForEach(x => x.Class_A = new_a);
2. What is the best way to update all values, if I'll have this code?
public class Class_D
{
public string my_field { get; set; }
public List<Class_A> list_A { get; set; }
// etc...
}
List<Class_D> list_D = new List<Class_D>(); //and then populate it

Have a look at ObservableCollection and Item PropertyChanged
You can make from your list_A an observable collection when can be received by Class_B and Class_C.

Related

Is it possible to add grouping on the index's of array column in an Observable Collection?

I have an ObservableCollection with a predefined class, Currently the ObservableCollection is displayed in a DataGrid using ICollectionView and grouped by columns sl_Id, sl_Name, sl_Date.
However i would like to know if its possible to group by the index's of sl_struct, the length of the array is determined at runtime.
public class SyncLog
{
public string sl_ID { get; set; }
public string sl_Name { get; set; }
public string sl_Date { get; set; }
public string sl_Type { get; set; }
public string[] sl_Struct { get; set; }
public string sl_SourceMachine { get; set; }
public string sl_Source { get; set; }
public string sl_DestMachine { get; set; }
public string sl_Dest { get; set; }
public bool sl_Success { get; set; }
public string sl_Time { get; set; }
public string sl_Size { get; set; }
}
current code for grouping
ICollectionView backupLogView = CollectionViewSource.GetDefaultView(Synclog);
PropertyGroupDescription group1 = new PropertyGroupDescription("sl_Id");
PropertyGroupDescription group2 = new PropertyGroupDescription("sl_Name");
PropertyGroupDescription group3 = new PropertyGroupDescription("sl_Date");
backupLogView.GroupDescriptions.Add(group1);
backupLogView.GroupDescriptions.Add(group2);
backupLogView.GroupDescriptions.Add(group3);
backupLogView.SortDescriptions.Add(new SortDescription("sl_Id", ListSortDirection.Ascending));
backupLogView.SortDescriptions.Add(new SortDescription("sl_Name", ListSortDirection.Ascending));
backupLogView.SortDescriptions.Add(new SortDescription("sl_Date", ListSortDirection.Ascending));
backupLogView.SortDescriptions.Add(new SortDescription("sl_Time", ListSortDirection.Ascending));
backupLogView.Refresh();
If new PropertyGroupDescription("sl_Struct.Length") doesn't work, though it probably should, you can just add another property to your SyncLog class that returns sl_Struct.Length
public class SyncLog
{
public string[] sl_Struct { get; set; }
public int sl_StructLength => sl_Struct?.Length ?? 0;
}
...
PropertyGroupDescription group = new PropertyGroupDescription("sl_StructLength ");
If you can't add a property to the SyncLog class(for example, if it is some external DTO), then you should probably create a specialized SyncLogViewModel that wraps the regular SyncLog and adds the sl_StructLength
public class SyncLogViewModel
{
private readonly SyncLog _syncLog;
public SyncLogViewModel(SyncLog syncLog) =>
_syncLog = syncLog ?? throw new ArgumentNullException(nameof(syncLog));
public int sl_StructLength => _syncLog.sl_Struct?.Length ?? 0;
public int sl_Struct
{
get => _syncLog.sl_Struct;
set => _syncLog.sl_Struct = value;
}
// Other properties...
}

Remembering the Syntax for adding a list inside a list

there I have done this before but forgotten the syntax. I am making a JSON file which looks list the classes below but on the submit button I want to add them but I can't remember the syntax for when there is a list inside a list if that makes sense! my classes are:
public class LineItemCheck
{
public string Id { get; set; }
public string Check { get; set; }
public bool Yes { get; set; }
public bool No { get; set; }
}
public class LineItem
{
public string Category { get; set; }
public List<LineItemCheck> LineItemChecks { get; set; }
}
public class RootObject
{
public object SerialNumber { get; set; }
public object UnitNumber { get; set; }
public object Refrigerant { get; set; }
public object ModelNumber { get; set; }
public object BeltSize { get; set; }
public object FreezingUnitComments { get; set; }
public object VisualInspectionComments { get; set; }
public List<LineItem> LineItems { get; set; }
}
private void SubmitButton_Clicked(object sender, EventArgs e)
{
var checklist = new RootObject();
var checklistLineItem = new List<LineItem>();
var checklistLineItemChecks = new List<LineItemCheck>();
checklist.SerialNumber = SerialNumber.Text.ToString();
checklist.UnitNumber = UnitNumber.Text.ToString();
checklist.Refrigerant = Refrigerant.Text.ToString();
checklist.ModelNumber = ModelNumber.Text.ToString();
checklist.BeltSize = BeltSize.Text.ToString();
checklistLineItem.Add(new LineItem() {
Category = "Ziegra Machines Only",
LineItemChecks = new LineItemCheck(LineItemCheck.
),
});
as you can see the bottom section is wrong which is what i am trying to solve thanks
UPDATE: I remember the syntax myself sorry for posting but the answer i was looking for was:
var checklist = new RootObject();
var checklistLineItem = new List<LineItem>();
var checklistLineItemChecks = new List<LineItemCheck>();
checklist.SerialNumber = SerialNumber.Text.ToString();
checklist.UnitNumber = UnitNumber.Text.ToString();
checklist.Refrigerant = Refrigerant.Text.ToString();
checklist.ModelNumber = ModelNumber.Text.ToString();
checklist.BeltSize = BeltSize.Text.ToString();
checklistLineItem.Add(new LineItem() {
Category = "Ziegra Machines Only",
LineItemChecks = new List<LineItemCheck>()
{
new LineItemCheck()
{
Check = "",
},
new LineItemCheck()
{
Check = ""
}
}
});
If I understand your question correctly the following should be the right syntax:
checklistLineItem.Add(new LineItem()
{
Category = "Ziegra Machines Only",
LineItemChecks = new List<LineItemCheck>()
{
new LineItemCheck(),
new LineItemCheck(), ...
},
});
If I may: I would amend your models like so.
public class LineItem
{
public string Category { get; set; }
public List<LineItemCheck> LineItemChecks { get; private set; }
public LineItem()
{
LineItemChecks = new List<LineItemCheck>();
}
}
public class RootObject
{
public object SerialNumber { get; set; }
public object UnitNumber { get; set; }
public object Refrigerant { get; set; }
public object ModelNumber { get; set; }
public object BeltSize { get; set; }
public object FreezingUnitComments { get; set; }
public object VisualInspectionComments { get; set; }
public List<LineItem> LineItems { get; private set; }
public RootObject()
{
LineItems = new List<LineItem>();
}
}
That is, initializing all the collections in a constructor. Properties that expose collections and that can be null are ugly and, more importantly, unexpected. I never expect a collection to be null if it's exposed through a property, I expect it to just be empty, and that I can add stuff to it right away. I'm not in charge of a collection exposed by your object, it's your object's business to initialize itself properly.
This is the consensus in .NET land, you will be hard-pressed to find an example of a collection exposed by a library that is null upon instantiation of the object.
Also notice that I made the setters private, because no other object should be able to flat-out replace a collection exposed by a different object.
Then adding items to collections is simply a matter of:
var root = new RootObject();
var lineItem = new LineItem();
lineItem.LineItemChecks.Add(new LineItemCheck() { /* init properties here */ });
root.LineItems.Add(lineItem);

Ignore Mapping of inner list property in AutoMapper --EF6,C#

I have a collection property of DTO like this
public ICollection<Applicant> Applicants{get;set;}
Applicant Model
public class Applicant
{
public int Id{get;set;}
public string name{get;set;}
public ICollection<ApplicantSkillsVM> ApplicantSkills { get; set; }
}
public class ApplicantSkillsVM
{
public int Id {get;set;}
public Skill skill{get;set;}
}
I want to map my List<iApplicant> DTO to entity given that I want to take ApplicantSkillsVM but ignore skill inside ApplicantSkillsVM.
I have a model which is list List<Applicant> and that contains another list List<ApplicantSkillsVM> and ApplicantSkillsVM has a property skill. I want to ignore this (skill) while mapping. Its simple.
How can I do this in latest the AutoMapper version with EF6?
Here a running sample:
internal class Program
{
#region Methods
private static void Main(string[] args)
{
// Configure the mappings
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ApplicantSkillVM, ApplicantSkill>().ForMember(x => x.Skill, x => x.Ignore()).ReverseMap();
cfg.CreateMap<ApplicantVM, Applicant>().ReverseMap();
});
var config = new MapperConfiguration(cfg => cfg.CreateMissingTypeMaps = true);
var mapper = config.CreateMapper();
ApplicantVM ap = new ApplicantVM
{
Name = "its me",
ApplicantSkills = new List<ApplicantSkillVM>
{
new ApplicantSkillVM {SomeInt = 10, SomeString = "test", Skill = new Skill {SomeInt = 20}},
new ApplicantSkillVM {SomeInt = 10, SomeString = "test"}
}
};
List<ApplicantVM> applicantVms = new List<ApplicantVM> {ap};
// Map
List<Applicant> apcants = Mapper.Map<List<ApplicantVM>, List<Applicant>>(applicantVms);
}
#endregion
}
/// Your source classes
public class Applicant
{
#region Properties
public List<ApplicantSkill> ApplicantSkills { get; set; }
public string Name { get; set; }
#endregion
}
public class ApplicantSkill
{
#region Properties
public Skill Skill { get; set; }
public int SomeInt { get; set; }
public string SomeString { get; set; }
#endregion
}
// Your VM classes
public class ApplicantVM
{
#region Properties
public List<ApplicantSkillVM> ApplicantSkills { get; set; }
public string Description { get; set; }
public string Name { get; set; }
#endregion
}
public class ApplicantSkillVM
{
#region Properties
public Skill Skill { get; set; }
public int SomeInt { get; set; }
public string SomeString { get; set; }
#endregion
}
public class Skill
{
#region Properties
public int SomeInt { get; set; }
#endregion
}
}
Initially my model ApplicantSkillsVM didnt have reference Id for Skill which should be nullable
So my model had to look like
public class ApplicantSkillsVM{
public int Id {get;set;}
public int? skillId{get;set;} //updated property
public Skill skill{get;set;}
}
The problem resolved

Convert flat to hierarchy list?

I have two tables "CategoryGroup" and "Category" which returns data in one list. Requirement is to convert flat list to hierarchy list like CategoryGroup contains related categories.
Please suggest how to convert into hieararchy list?
public class ProfileConditionGroup
{
public Guid ConditionGroupGUID { get; set; }
public string ConditionGroupName { get; set; }
public List<ProfileConditionList> profileConditions { get; set; }
}
public class ProfileConditionList
{
public string ConditionName { get; set; }
public Nullable<Guid> ConditionGUID { get; set; }
public string[] ThisConditionSelectedByProfileIDs { get; set; }
public Nullable<Guid> ParentConditionGroupGUID { get; set; }
public bool IsDefaultSelected { get; set; }
}
This is actually a little tricky without having an actual concrete return type, but here's the way I'd tackle it if you're just building a tree of Guid values.
Given this query:
var query =
from pcg in pcgs
from pcl in pcg.profileConditions
select new
{
pcg.ConditionGroupName,
pcg.ConditionGroupGUID,
pcl.ConditionName,
pcl.ConditionGUID,
pcl.ThisConditionSelectedByProfileIDs,
pcl.ParentConditionGroupGUID,
pcl.IsDefaultSelected,
};
...I'd do this:
var lookup = query.ToLookup(x => x.ParentConditionGroupGUID);
Func<Guid?, Tree<Guid?>> build = null;
build = g =>
{
var r = new Tree<Guid?>() { Value = g };
r.AddRange(lookup[g].Select(x => build(x.ConditionGroupGUID)));
return r;
};
Now you just call build(null) and you should get a tree of Guid?. If you can create you're own output class you'd change the function to Func<Guid?, Tree<YourOutputClass>>.
You need this class for the tree:
public class Tree<T> : List<Tree<T>>
{
public T Value { get; set; }
}

Instantiate the field of an Automatic propertiy automatically in C#

this is my Model:
public class Schoolclass
{
private List<Pupil> _pupils;
public Schoolclass()
{
_pupils = new List<Pupil>();
}
public int SchoolclassId { get; set; }
public string SchoolclassCode { get; set; }
public List<Pupil> Pupils
{
get { return _pupils;}
set { _pupils = value; }
}
}
Can I do this somehow with C# only without 3rd-party tools:
[Initialize]
public List<Pupil> Pupils {get;set}
I want that C# generates the field _pupils automatically.
There is no automatic way, but you can still assign the property in the constructor:
public Schoolclass()
{
Pupils = new List<Pupil>();
}
Also, since Pupils is a collection, I would suggest making it read-only:
public List<Pupil> Pupils {get; private set;}
Update
Full class would look like so:
public class Schoolclass
{
public Schoolclass()
{
Pupils = new List<Pupil>();
}
public int SchoolclassId { get; set; }
public string SchoolclassCode { get; set; }
public List<Pupil> Pupils { get; private set; }
}

Categories

Resources