List Updating a value after Insert - c#

i have a issue, I want to Update a value to element which is getting added in a list.
With generic example:-
I have a Model Object:-
public class Model
{
public int ModelProperty1 { get; set; }
public int ModelProperty2 { get; set; }
public int ModelPropertyStatus { get; set; }
}
I have a DTO Object:-
public class DTO
{
public int DTOProperty1 { get; set; }
public int DTOProperty2 { get; set; }
public int DTOPropertyStatus { get; set; }
}
Now, in my Controller i have a List which adds Model object:-
List<Model> _listOfModel = new List<Model>();
Secondly, i have created a mapping method which maps my Model & DTO
private Model MapDTOToModel(DTO dto)
{
return new Model
{
ModelProperty1 = dto.DTOProperty1,
ModelProperty2 = dto.DTOProperty2
};
}
Coming to my Issue:-
I want something like this to work:-
//I want a piece of code that Updates my ModelPropertyStatus after it gets inserted to //List
_listOfModel.Add(new Model() { ModelPropertyStatus = 1 });
//Here is the piece of code i want to convert:-
Model model = new Model();
model.ModelPropertyStatus = 1;
_listOfModel.Add(MapDTOToModel(model));
To be specific(Updated)
I want something like this:-
_listOfModel.Add(MapDTOToModel() { ModelPropertyStatus = 1 });
Any Suggestions??

You are looking for an ObservableCollection:
Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
Here's an example:
public class Model
{
public int ModelProperty1 { get; set; }
public int ModelProperty2 { get; set; }
public int ModelPropertyStatus { get; set; }
}
void Main()
{
ObservableCollection<Model> _listOfModel = new ObservableCollection<Model>();
_listOfModel.CollectionChanged += (s, o) =>
{
foreach (var m in o.NewItems)
((Model)m).ModelPropertyStatus = 1;
};
var model = new Model();
Console.WriteLine("Before add: " + model.ModelPropertyStatus.ToString());
_listOfModel.Add(model);
Console.WriteLine("After add: " + model.ModelPropertyStatus.ToString());
}
output:
Before add: 0
After add: 1
As you can see, using the CollectionChanged event, the property gets updatet during the insert.

Related

How to recursively map one nested object type to another

I would like to map the data from one list of objects and another. I am looping through CompanyAEmployee list and able to map FullName and Title. But not able to map Children property.
public class CompanyAEmployee
{
public string FullName { get; set; }
public string Title { get; set; }
public List<CompanyAEmployee> Children { get; set; }
}
public class CompanyBEmployee
{
public string Name { get; set; }
public string PositionName { get; set; }
public List<CompanyBEmployee> Children { get; set; }
}
companyAEmployeeList; // stores all employees of companyA
var companyBEmployeeList = new List<CompanyBEmployee>();
foreach(var employee in companyAEmployeeList)
{
var companyBEmployee = new CompanyBEmployee();
companyBEmployee.Name = employee.FullName;
companyBEmployee.PositionName = employee.Title;
//how to map the children??
}
Can someone suggest a way to map Children?
You can create a recusive method, like below:
public CompanyBEmployee ComAToComB(CompanyAEmployee a){
CompanyBEmployee b = new(){
Name = a.FullName,
PositionName = a.Title,
Children = new()
};
foreach(var child in a.Children){
b.Children.Add(ComAToComB(child));
}
return b;
}
And then call it like
var comB = ComAToComB(comA);
So, in my case it was best solution to use extension methods.
You can see example here
https://dotnetfiddle.net/SwhGMY
Main idea is to use such extension method that was called recursively.
public static class ClassConverterExtensions
{
public static CompanyBEmployee ToCompanyBEmployee(this CompanyAEmployee that)
{
var result = new CompanyBEmployee();
result.Name = that.FullName;
result.PositionName = that.Title;
if(that.Children == null)
{
return result;
}
result.Children = new List<CompanyBEmployee>();
foreach(var item in that.Children)
{
result.Children.Add(item.ToCompanyBEmployee());
}
return result;
}
}
Good point is that you can write this without changing source code of classes CompanyBEmployee and CompanyAEmployee
So, this classes is not referenced one to another, but you can write converters From A to B and from B to A without cyclic references.
Here is the solution:
public class CompanyAEmployee
{
public string FullName { get; set; }
public string Title { get; set; }
public List<CompanyAEmployee> Children { get; set; }
public static explicit operator CompanyBEmployee(CompanyAEmployee employee)
{
CompanyBEmployee employee1 = new CompanyBEmployee();
employee1.Name = employee.FullName;
employee1.PositionName = employee.Title;
employee1.Children = new List<CompanyBEmployee>(employee.Children.Count);
int count = employee.Children.Count;
for (int i = 0; i < count; i++)
employee1.Children[i] = (CompanyBEmployee)employee.Children[i];
return employee1;
}
}
public class CompanyBEmployee
{
public string Name { get; set; }
public string PositionName { get; set; }
public List<CompanyBEmployee> Children { get; set; }
}
Now you can just use an assignment operator with explicit casting from CompanyAEmployee to CompanyBEmployee.
Like this:
CompanyAEmployee employee = new CompanyAEmployee();
//... assign all the fields
CompanyBEmployee employee2 = (CompanyBEmployee)employee.
Now you are done!

C# UWP - Adding object to ObservableCollection causes XAML generated UnhandledException

I have an ObservableCollection<DiscoveredScooter> DiscoveredScooters = new ObservableCollection<DiscoveredScooter>. The DiscoveredScooter class looks like this:
public class DiscoveredScooter : ViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Model { get; set; }
public int RSSI { get; set; }
public DiscoveredScooter(string id, string name, string model, int rssi)
{
Id = id;
Name = name;
Model = model;
RSSI = rssi;
}
public void Update(DeviceInformationUpdate d, string model, int rssi)
{
Id = d.Id;
RSSI = rssi;
Model = model;
RaisePropertyChanged(nameof(Id));
RaisePropertyChanged(nameof(RSSI));
RaisePropertyChanged(nameof(Model));
}
public void UpdateRSSI(int rssi)
{
RSSI = rssi;
RaisePropertyChanged(nameof(RSSI));
}
}
My XAML has a Listview which is bound to this ObservableCollection. I have a BluetoothAdvertismentEvent that gets fired whenever I receive advertisement data. I do some validation and then I do
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
DiscoveredScooters.Add(new DiscoveredScooter(args.BluetoothAddress.ToString(), bleDeviceName, beaconParser.HumanReadableModel, (int)args.RawSignalStrengthInDBm));
});
But this causes a "XAML generated UnhandledException" and it doesn't say any more about the error whatsoever. Here is a screenshot https://gyazo.com/42ee2cae9018c05087335f77db83cb99 Any help is appreciated.
The issue was that I was using .Substring(41) on a property, where the length was way less than that.

Sort MultiLevel Data with Linq

I have a data structure as follows:
public class BranchLevel_1
{
public string Name { get; set; }
public ObservableCollection<BranchLevel_2> Children { get; set; }
public BranchLevel_1(string name, List<BranchLevel_2> children)
{
this.Name = name;
this.Children = new ObservableCollection<BranchLevel_2>(children);
}
}
public class BranchLevel_2
{
public ObservableCollection<BranchLevel_3> Contents { get; set; }
public BranchLevel_2(List<string> contents)
{
this.Contents = new ObservableCollection<BranchLevel_3>();
for (int i = 0; i < contents.Count; i++)
{
this.Contents.Add(new BranchLevel_3(contents[i]));
}
}
}
public class BranchLevel_3
{
public string Content { get; set; }
public BranchLevel_3(string text)
{
this.Content = text;
}
}
Sorting data on the first level is easy and I can obtain in easily by:
Level1_Data.OrderBy(item => item.Name).ToList()
However, I am stuck with sorting on the second level. BranchLevel_2 class is just a container for items stored in BranchLevel_3 classes. Therefore I would like to sort Level2 with data stored in BranchLevel_2.Contents1.Content value. This syntax for me seems to be correct and I cannot locate the problem...
Level1_Data.Select(item_Level1 => item_Level1.Children.OrderBy(item_Level2 => item_Level2.Contents[1].Content)).ToList();
Any hints?
Here is the rusult (indicated in yellow is supposed to be sorted alphabetically)
Why not just sort the contents before adding them to the ObservableCollection
public class BranchLevel_2
{
public ObservableCollection<BranchLevel_3> Contents { get; set; }
public BranchLevel_2(List<string> contents)
{
this.Contents = new ObservableCollection<BranchLevel_3>();
foreach (var content in contents.OrderBy(c => c))
{
this.Contents.Add(new BranchLevel_3(content));
}
}
}
Here is a solution that solved the problem, thanks to suggestion from #bhmahler
public class BranchLevel_1
{
public string Name { get; set; }
public ObservableCollection<BranchLevel_2> Children { get; set; }
public BranchLevel_1(string name, List<BranchLevel_2> children)
{
this.Name = name;
//this line needs to be added before creating ObservableCollection
children.OrderBy(item_level2 => item_level2.Contents[1].Content).ToList();
this.Children = new ObservableCollection<BranchLevel_2>(children);
}
}

Sharing Object between Views & ViewModels in MVVM

I'm new to WPF + MVVM and have been having trouble getting around viewmodels.
I have a object called FSystem which contains a alot of lists which are populated from a XML.
public class FSystem : ObservableObject
{
public List<FUser> _userList;
public List<FZone> _zoneList;
public List<FSource> _sourceList;
public string _projectName { get; set; }
private string _projectVersion { get; set; }
private string _processorIp { get; set; }
private bool _isMultiLingualModeOn { get; set; }
private int _systemIncludeLighting { get; set; }
private int _systemIncludeWindowsTreatments { get; set; }
private int _systemIncludeSip { get; set; }
private int _systemIncludeCamaras { get; set; }
public FSystem()
{
UserList = new List<FUser>();
}
}
This is the XMLParser which is called when the user loads the XML to the application.
public static class XMLParsers
{
public static FSystem ParseByXDocument(string xmlPath)
{
var fSystem = new FSystem();
XDocument doc = XDocument.Load(xmlPath);
XElement fSystemElement = doc.Element("FSystem");
if (fSystemElement != null)
{
fSystem.ProjectName = fSystemElement.Element("ProjectName").Value;
fSystem.ProjectVersion = fSystemElement.Element("ProjectVersion").Value;
fSystem.ProcessorIp = fSystemElement.Element("ProcessorIP").Value;
fSystem.ProcessorFilePath = fSystemElement.Element("ProcessorFilePath").Value;
fSystem.SystemIncludeLighting = Convert.ToInt16(fSystemElement.Element("SystemIncludeLighting").Value);
fSystem.SystemIncludeSip = Convert.ToInt16(fSystemElement.Element("SystemIncludeLighting").Value);
fSystem.SystemIncludeCamaras = Convert.ToInt16(fSystemElement.Element("SystemIncludeCameras").Value);
}
fSystem.UserList = (from user in doc.Descendants("FUser")
select new FUser()
{
Id = user.Element("Id").Value,
Name = user.Element("Name").Value,
Icon = user.Element("IconColour").Value,
Pin = user.Element("UserPin").Value,
IsPinEnabled = Convert.ToBoolean(Convert.ToInt16(user.Element("UserPinEnabled").Value)),
ListIndex = user.Element("ListIndex").Value
}).ToList();
return fSystem;
}
}
And this is the MainViewModel below is what contains the Commands which Load the XML and the property FSystem I wish to use in other view models.
public class MainViewModel : ViewModel
{
private Fystem fSystem;
public FSystem FSystem
{
get { return fSystem; }
private set
{
fSystem = value;
NotifyPropertyChanged("FSystem");
}
}
public MainViewModel()
{
InitiateState();
WireCommands();
}
private void InitiateState()
{
FSystem = new FSystem();
}
private void WireCommands()
{
XDocumentLoadCommand = new RelayCommand(XDocumentLoad) {IsEnabled = true};
ClearDataCommand = new RelayCommand(ClearData) {IsEnabled = true};
}
public RelayCommand XDocumentLoadCommand { get; private set; }
private void XDocumentLoad()
{
var openDlg = new OpenFileDialog
{
Title = "Open .FAS",
DefaultExt = ".fas",
Filter = "F System Files (*.fas)|*.fas",
Multiselect = false
};
bool? result = openDlg.ShowDialog() == DialogResult.OK;
if (result != true) return;
FSystem = XMLParsers.ParseByXDocument(openDlg.FileName);
}
The application basically lets the user change the different objects (FUser,FZone,FSource, ect). The idea I had was the user would load the XML then be able to edit the different list objects on different views.
What would the correct way be to go about this in MVVM?
I plan to (hopefully) get the User, Zone and Source views to display Datagrids which are populated with their respective data from the Model.
Create you specific view models, and use dependency injection to pass the relevant data into them (this list or that list).
This way, the view models don't need to know about other stuff, and you can easily mock it for testing and for dummy data to see on the designer.
Copy paste into Linqpad for the simplest example. Both mock viewmodels take a dependency (i in our case). You can just pass your lists:
void Main()
{
int someInt = 5;
int anotherInt = 7;
VM vm1 = new VM(someInt);
VM vm2 = new VM(anotherInt);
vm1.RevealI();
vm2.RevealI();
}
public class VM{
private int _i;
public VM(int i)
{
_i = i;
}
public void RevealI() { Console.WriteLine("value of i is: " + _i); }
}
Othen than that, here's more items:
MSDN
Code Project
stack overflow

NullReference when Adding to nested list

I have class
public class Gallery
{
public string method { get; set; }
public List<List<object>> gidlist { get; set; }
public int #namespace { get; set; }
}
Button code
private void button1_Click(object sender, EventArgs e)
{
List<object> data = new List<object>();
data.Add(618395);
data.Add("0439fa3666");
Gallery jak = new Gallery();
jak.method = "gdata";
jak.gidlist.Add(data);
jak.#namespace = 1;
string json = JsonConvert.SerializeObject(jak);
textBox2.Text = json;
}
Here I get System.NullReferenceException. How to add item to gidlist ?
You get it because in now place you initialized the list within jak.
You can:
Add a default constructor and initialize list there:
public class Gallery
{
public Gallery()
{
gidlist = new List<List<object>>();
}
public string method { get; set; }
public List<List<object>> gidlist { get; set; }
public int #namespace { get; set; }
}
If in C# 6.0 then you can use the auto-property initializer:
public List<List<object>> gidlist { get; set; } = new List<List<object>>()
If in under C# 6.0 and don't want the constructor option for some
reason:
private List<List<object>> _gidlist = new List<List<object>>();
public List<List<object>> gidlist
{
get { return _gidlist; }
set { _gidlist = value; }
}
You can just initialize it before using (I don't recommend this option)
Gallery jak = new Gallery();
jak.method = "gdata";
jak.gidlist = new List<List<object>>();
jak.gidlist.Add(data);
jak.#namespace = 1;
If before C# 6.0 best practice will be option 1. If 6.0 or higher then option 2.

Categories