Update multiple properties on event raised - c#

I am trying to understand how to trigger all the properties update when new data available.
For example I have two properties:
public string PropertyOne
{
get
{
return _propertyOne
}
set
{
_propertyOne= value;
this.OnPropertyChanged();
}
}
public string PropertyTwo
{
get
{
return _propertyTwo;
}
set
{
_propertyTwo = value;
this.OnPropertyChanged();
}
}
When I receive notification about new data I assign my properties:
Mediator<ViewModelMessages>.Instance.Register(ViewModelMessages.OnNewData, this.OnNewData);
private void OnNewData(object obj)
{
PropertyOne = (MyClass)obj.propertyOne;
PropertyTwo = (MyClass)obj.propertyTwo;
}
What I want to have is something like this:
private MyClass _myClass;
private void OnNewData(object obj)
{
_myClass = (MyClass)obj;
}
public string PropertyOne
{
get
{
return _myClass.PropertyOne;
}
set
{
_myClass.PropertyOne = value;
this.OnPropertyChanged();
}
}
public string PropertyTwo
{
get
{
return _myClass.propertyTwo;
}
set
{
_myClass.propertyTwo = value;
this.OnPropertyChanged();
}
}
So when new data arrived, my properties are automatically updated.

You can achieve that by passing an Empty string or null to your OnPropertyChanged rather than a property name, but note that property changed will get raised for all properties in this case.

Related

JSON Deserialization not calling property methods

I have a JSON class file which contains three classes, all of which follow this structure:
public class ManifestJSON : INotifyPropertyChanged
{
[JsonProperty("dataType")]
private string dataType;
public string DataType
{
get
{
return dataType;
}
set
{
if(dataType != value)
{
dataType = value;
RaisePropertyChanged("DataType");
}
}
}
[JsonProperty("ttl")]
private int time_to_live;
public int Time_To_Live
{
get
{
return time_to_live;
}
set
{
if (time_to_live != value)
{
time_to_live = value;
RaisePropertyChanged("Time_To_Live");
}
}
}
[JsonProperty("serial")]
private long serial;
public long Serial
{
get
{
return serial;
}
set
{
if (serial != value)
{
serial = value;
RaisePropertyChanged("Serial");
}
}
}
[JsonProperty("modifiedIso8601")]
private string modifiedIso8601;
public string ModifiedIso8601
{
get
{
return modifiedIso8601;
}
set
{
if (modifiedIso8601 != value)
{
modifiedIso8601 = value;
RaisePropertyChanged("ModifiedIso8601");
}
}
}
[JsonProperty("modifiedTimestamp")]
private long modifiedTimestamp;
public long ModifiedTimestamp
{
get
{
return modifiedTimestamp;
}
set
{
if (modifiedTimestamp != value)
{
modifiedTimestamp = value;
RaisePropertyChanged("ModifiedTimestamp");
}
}
}
[JsonProperty("timezone")]
private string timezone;
public string Timezone
{
get
{
return timezone;
}
set
{
if (timezone != value)
{
timezone = value;
RaisePropertyChanged("Timezone");
}
}
}
[JsonProperty("exports")]
private ObservableCollection<ManifestItem> manifest_Items;
public ObservableCollection<ManifestItem> Manifest_Items
{
get
{
return manifest_Items;
}
set
{
if (manifest_Items != value)
{
manifest_Items = value;
RaisePropertyChanged("Manifest_Items");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
In another class, I've created a global instance of type ManifestJSON
public ManifestJSON manifestData;
which is filled by deserializing a JSON string into this object using the DeserializeObject method from the Newtonsoft.json library like so:
manifestData = JsonConvert.DeserializeObject<ManifestJSON>(JSONString).
This fills the ManifestJSON class successfully, but none of my property methods or events are triggering. What am I doing wrong here?
If you want to update your existing data-bound ManifestJSON object, you should not replace this one with a new object but de-serialize the JSON string into new object and then set the properties of the existing manifestData object:
var newData = JsonConvert.DeserializeObject<ManifestJSON>(JSONString);
manifestData.DataType = newData.DataType;
manifestData.Time_To_Live = newData.Time_To_Live;
manifestData.Serial = newData.Serial;
//...

C# Communication between parent form and child form

My project has two classes. The first class has information about continents and it contains also a list of objects of countries (another class).
I also declared a list of continents that contains all the continents.
I've succeeded in filling the list from a file, and succeeded to show them in a DataGridView in the same form. But the problem is that I didn't find a way to show them in a child form that contains a DataGridView.
So, how can I transfer the list of continents to the child form so that I can be able to show them in it?
I tried serialiization and deserialization, but it didn't work, I just see the name of members of continent class and nothing else.
Here are the two class and code of toolstrip that show the child form:
// first class of continent
namespace WindowsFormsApplication1
{
[Serializable]
class continent
{
//champs
private string nomc;
public string Nomc
{
get { return this.nomc; }
}
private string sup;//SUP
public string Superficie
{
get { return this.sup; }
set { this.sup = value; }
}
private string pop;//POP
public string Population
{
get { return this.pop; }
set { this.pop = value; }
}
private string dens;//DENS :
public string Densité
{
get { return this.dens; }
set { this.dens = value; }
}
private string nbp;//NBP : 54 :
public string nombre_de_Pays
{
get { return this.nbp; }
set { this.nbp = value; }
}
private string fus;//FUS )
public string Fuseaux_horaires
{
get { return this.fus; }
set { this.fus = value; }
}
private string pnb;//PNB
public string PNB_habitant
{
get { return this.pnb; }
set { this.pnb = value; }
}
//constructeur
public continent(string nom)
{
this.nomc = nom;
}
public continent()
{
// TODO: Complete member initialization
}
//list of countries of that continent
public List<country> listep = new List<country>();
}
// class of countries
namespace WindowsFormsApplication1
{
[Serializable]
class country
{
//champs
private string nom_p;
public string Nom_pays
{
get { return this.nom_p; }
set { this.nom_p = value; }
}
private string cap;//PCAP
public string Capitale
{
get { return this.cap; }
set { this.cap = value; }
}
private string sup;// PSUP
public string Superficie
{
get { return this.sup; }
set { this.sup = value; }
}
private string reg;// REG
public string Régime_politique
{
get { return this.reg; }
set { this.reg = value; }
}
private string dev;//PDEV nationale
public string Devise
{
get { return this.dev; }
set { this.dev = value; }
}
private string hym;// PHYM
public string Hymne
{
get { return this.hym; }
set { this.hym = value; }
}
private string lg;// PLG
public string Langue
{
get { return this.lg; }
set { this.lg = value; }
}
private string mo;// PMO
public string Monnaie
{
get { return this.mo; }
set { this.mo = value; }
}
private string de;
public string PDE
{
get { return this.de; }
set { this.de = value; }
}
//constructeur
public country (string nom)
{
this.nom_p = nom;
}
}
}
and the code in the form is
//liste of contnents
List<continent> listec = new List<continent>();
// i filled it from a file
//here the code of toolstrip that open the childform
private void listeContinentToolStripMenuItem_Click(object sender, EventArgs e)
{
listecont flc = new listecont();
flc.ShowDialog();
flc.MdiParent = this;
}
In your child form, add an overload to the Form constructor that takes a Form as an argument. Then when you create your child form, you can pass in an instance of your current (parent) form like, listecont flc = new listecont(this); where this is a reference of your parent form. Now your child form can make calls to parentForm.Textbox.Text = "blablabal" or what ever object you want to interact with.
Why not just add a constructor to the listecont class that takes a List<continent>? Then, the child form will have the data when it's constructed.
in your MDI child add a method:
public void SetContinentData(List<continent> list)
{
// add your DataSource to the grid
// f.e.:
dataGridView.DataSource = list;
}
and in your Toolstrip handler:
private void listeContinentToolStripMenuItem_Click(object sender, EventArgs e)
{
listecont flc = new listecont();
flc.SetContinentData(listec);
flc.ShowDialog();
flc.MdiParent = this;
}

Custom Collection/List To Store Custom Objects

I have a customer object class:
public class customerObject
{
private string _address1;
private string _address2;
private string _address3;
private string _category;
private string _country;
private string _county;
private string _custcode;
private string _fullname;
private string _int_rep_hou;
private string _int_rep_key;
private double _lat;
private double _lng;
private string _postcode;
private string _rep_code;
private string _telephone;
public customerObject()
{
}
public string Address1
{
get { return _address1; }
set { _address1 = value; }
}
public string Address2
{
get
{
return _address2;
}
set { _address2 = value; }
}
public string Address3 { get { return _address3; } set { _address3 = value; } }
public string Category
{
get { return _category; }
set { _category = value; }
}
public string Country { get { return _country; } set { _country = value; } }
public string County { get { return _county; } set { _county = value; } }
public string Custcode
{
get { return _custcode; }
set { _custcode = value; }
}
public string Fullname
{
get { return _fullname; }
set { _fullname = value; }
}
public string Int_rep_hou
{
get { return _int_rep_hou; }
set { _int_rep_hou = value; }
}
public string Int_rep_key
{
get { return _int_rep_key; }
set { _int_rep_key = value; }
}
public double Lat { get { return _lat; } set { _lat = value; } }
public double Lng { get { return _lng; } set { _lng = value; } }
public string Postcode { get { return _postcode; } set { _postcode = value; } }
public string Rep_code
{
get { return _rep_code; }
set { Rep_code = value; }
}
public string Telephone { get { return _telephone; } set { _telephone = value; }
}
}
I have a CustomCollections class
public class CustomerCollection
{
public List<customerObject> Customers { get; set; }
}
My method that loops through dt rows and converts to a customer object
public List<Valueobjects.CustomerCollection> dolist(DataTable temptablename)
{
//Create Collection Object
Valueobjects.CustomerCollection Collection = new Valueobjects.CustomerCollection();
foreach (DataRow row in temptablename.Rows)
{
//Create Customer Object
Valueobjects.customerObject Customer = new Valueobjects.customerObject();
//set values of customer object
Customer.Rep_code = "";
Customer.Int_rep_key = "";
Customer.Int_rep_hou = "";
Customer.Fullname = row["Fullname"].ToString().Trim();
Customer.Custcode = row["Custcode"].ToString().Trim();
Customer.Category = row["Category"].ToString().Trim();
Customer.Address1 = row["Address1"].ToString().Trim();
Customer.Address2 = row["Address2"].ToString().Trim();
Customer.Address3 = row["Address3"].ToString().Trim();
Customer.Postcode = row["Postcode"].ToString().Trim();
Customer.Country = row["Country"].ToString().Trim();
Customer.Telephone = row["Telephone"].ToString().Trim();
Customer.Lat = Convert.ToDouble(row["Lat"]);
Customer.Lng = Convert.ToDouble(row["Lng"]);
Customer.County = row["County"].ToString().Trim();
//add to the collection (list)
Collection.Customers.Add(Customer);
}
temptablename = null;
return Collection;
}
However when I create a new Customer object and a new CustomerCollection object I am getting an error when adding the customer to the collection list.
Error:
Error 32 Cannot implicitly convert type
'Classes.Valueobjects.CustomerCollection' to
'System.Collections.Generic.List'
Your method is returning a List<CustomerCollection>:
public List<Valueobjects.CustomerCollection> dolist(DataTable temptablename)
{
//...
}
But the code is trying to return a CustomerCollection:
return Collection;
Just as the error says, these two types are different.
If a CustomerCollection is already a collection of customers, then semantically what is a List<Valueobjects.CustomerCollection>? A collection of collections? It seems like you're over-pluralizing your objects :)
There are two approaches here. Either return a CustomerCollection from the method:
public CustomerCollection dolist(DataTable temptablename)
{
//...
}
Or use a List<Customer> if you want to use generic lists as your collection containers:
public List<Customer> dolist(DataTable temptablename)
{
//...
var Collection = new List<Customer>();
//...
Collection.Add(Customer);
//...
return Collection;
}
Side note: You may want to stick to C# conventions for variable naming. As you can see from the code highlighting here on Stack Overflow, your variable names can easily be mistaken for classes/types, which can cause confusion when supporting the code.
Return a CustomerCollection instead of a List<Valueobjects.CustomerCollection>:
public Valueobjects.CustomerCollection Dolist(DataTable temptablename)
{
// ...
Your object has a list, it is not a list.
MSDN: Inheritance

C# - Marshall by value problem!

Here is the thing, I have a problem creating a new object using the remote mechanism "marshal by value".
Here is my class:
[Serializable]
internal class Empleado_MBV
{
public Empleado_MBV()
{
Id = 123456789;
Nombres = "NotEntry";
Apellidos = "NotEntry";
FechaNacimiento = DateTime.MinValue;
Direccion = "NotEntry";
Metapreferencias = "NotEntry";
}
private List<Multas> _multas;
internal List<Multas> Multas
{
get { return _multas; }
set { _multas = value; }
}
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
private string _nombres;
public string Nombres
{
get { return _nombres; }
set { _nombres = value; }
}
private string _apellidos;
public string Apellidos
{
get { return _apellidos; }
set { _apellidos = value; }
}
private DateTime _FecNac;
public DateTime FechaNacimiento
{
get { return _FecNac; }
set { _FecNac = value; }
}
private string _direccion;
public string Direccion
{
get { return _direccion; }
set { _direccion = value; }
}
private string _metapreferencias;
public string Metapreferencias
{
get { return _metapreferencias; }
set { _metapreferencias = value; }
}
public string _AppDomainHost
{
get { return AppDomain.CurrentDomain.FriendlyName.ToString(); }
}
}
But when I try to create an object in another "appdomain", the property "_AppDomainHost" of "Empleado" does not show the "appdomain" I had created, but show the "appdomain" by default. Some ideas?
AppDomain ad1 = AppDomain.CreateDomain("NewAppDomain");
//Crear new object in my new AD.
Empleado_MBV mbv_emp = (Empleado_MBV)ad1.CreateInstanceFromAndUnwrap("DEMO_MBV_MBR.exe", "DEMO_MBV_MBR.Empleado_MBV");
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName.ToString());
Console.WriteLine("MBV : {0}",mbv_emp._AppDomainHost.ToString());
Console.ReadLine();
Result:
DEMO_MBV_MBR.vshost.exe
MBV : DEMO_MBV_MBR.vshost.exe
The result that I want:
DEMO_MBV_MBR.vshost.exe
MBV : NewAppDomain
You need to store AppDomain in Empleado_MBV's constructor.
What you are doing right now is displaying current AppDomain using its Current static property. It will return the AppDomain where current code is being executed.
Example:
private string _appDomainHost;
public string _AppDomainHost
{
get { return _appDomainHost; }
}
and in constructor:
_appDomainHost = AppDomain.CurrentDomain.FriendlyName.ToString();

C#/WPF: PropertyChanged for all Properties in ViewModel?

I've a class like this:
public class PersonViewModel : ViewModelBase //Here is the INotifyPropertyChanged Stuff
{
public PersonViewModel(Person person)
{
PersonEntity = person;
}
public Person PersonEntity {
get { return PersonEntity.Name; }
private set { PersonEntity.Name = value; RaisePropertyChanged("PersonEntity");
}
public string Name {
get { return PersonEntity.Name; }
set { PersonEntity.Name = value; RaisePropertyChanged("Name");
}
public int Age{
get { return PersonEntity.Age; }
set { PersonEntity.Age= value; RaisePropertyChanged("Age");
}
public void ChangePerson(Person newPerson)
{
//Some Validation..
PersonEntity = newPerson;
}
My TextBoxes are bound to Name and Age of the ViewModel.
If I change the _person object in the ViewModel, do I have to call for each Property a RaisePropertyChanged again or is there a way to do this automaticly (in my concret example I have about 15 Properties..)?
Thanks for any help.
Cheers
Joseph
You can indicate all properties have changed by using null or string.Empty for the property name in PropertyChangedEventArgs. This is mentioned in the documentation for PropertyChanged.
One other solution I used to tackle the problem of: first setting the value and then calling the PropertyChangedEventArgs is by adding a Set function in my ViewModelBase which looks like this:
public class ViewModelBase : INotifyPropertyChanged
{
protected bool Set<T>(ref T backingField, T value, [CallerMemberName] string propertyname = null)
{
// Check if the value and backing field are actualy different
if (EqualityComparer<T>.Default.Equals(backingField, value))
{
return false;
}
// Setting the backing field and the RaisePropertyChanged
backingField = value;
RaisePropertyChanged(propertyname);
return true;
}
}
Instead of doing this:
public string Name {
get { return PersonEntity.Name; }
set { PersonEntity.Name = value; RaisePropertyChanged("Name");
}
You can now achieve the same by doing this:
public string Name {
get { return PersonEntity.Name; }
set { Set(ref PersonEntity.Name,value);
}

Categories