I am fairly new to the MVVM design pattern and integrated one yesterday in my program with the help of a fellow user here. However, I can't seem to get the values of the variables into another class via the { get; } function. I tried fixing this for quiet some time now and this is my last resort. This is just the script integrated in a wpf form, but the error is here, so I just pasted the code I thought to be neccesary.
public class ViewModel
{
public IEnumerable<string> ServerNames { get; }
= new string[] { "s1", "s2" };
public string SSN { get; set; }
= "s1";
public string APort { get; set; }
= "9999";
public string FPort { get; set; }
= "9991";
public string HostName { get; set; }
= "localhost";
}
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
Now, my thought would be to get the values of the viewmodel by just using { get; }
private class Server
{
public string HostName { get; }
public string APort { get; }
public string FPort { get; }
public string SSN { get; }
}
But this would just leave the 4 variables with a NULL value instead of getting the data from the view model.
How can I get the values of the variables from the view model for further usage into my private class called "Server"?
EDIT:
The server class is initiated later:
private void WPFLoginButton_Click(object sender, RoutedEventArgs e)
{
try
{
Server server = new Server();
HAServerConnection aConnection =
new HAServerConnection(server.HostName, UInt16.Parse(server.APort), new HACalls(), new HErrors());
Of course the values of the properties will be null until you actually set them to some values. You don't seem to be doing this somewhere in your code, and there is no other piece of code that will do it for you.
You could either add setters to the properties and set them when you initialize the Server:
Server server = new Server() { HostName = viewModel.HostName, APort = viewModel.Aport };
Or you could define a constructor that accepts some values and set the properties:
private class Server
{
public Server(string hostName, string aPort, string fPort, string sSN)
{
HostName = hostName;
APort = aPort;
FPort = fPort;
SSN = sSN;
}
public string HostName { get; }
public string APort { get; }
public string FPort { get; }
public string SSN { get; }
}
You will still need to get the actual values from somewhere when you initialize the class, like for example from the view model.
Related
I have two classes made as:
public class ipAddress
{
public object ip { get; set; }
}
public class Rule
{
public string name { get; set; }
public ipAddress conditions { get; set; }
public string action { get; set; }
public Boolean enabled { get; set; }
public string statusCode { get; set; }
}
My code to create/assign values to this is:
Rule new_rule = new Rule();
ipAddress ip_info = new ipAddress();
ip_info.ip = new { ipAddress = "34.5.6.7.8" };
new_rule.name = "test";
new_rule.conditions = ip_info;
new_rule.action = "ALLOW";
new_rule.enabled = true;
new_rule.statusCode = "FORBIDDEN_403";
var rule_json = JsonConvert.SerializeObject(new_rule);
after serializing I get this output
{"name":"test","conditions":{"ip":{"ipAddress":"34.5.6.7.8"}},"action":"ALLOW","enabled":true,"statusCode":"FORBIDDEN_403"}
While my expected output is:
{"name":"test","conditions":[{"ip":{"ipAddress":"34.5.6.7.8"}}],"action":"ALLOW","enabled":true,"statusCode":"FORBIDDEN_403"}
so the only difference is the extra object wrapped around the conditions' values.
How can I accomplish this? Tried different things but didn't get there.
Thanks
public ipAddress conditions { get; set; }
The above statement means conditions is an object and objects are represented by { }. If you are expecting it to be a list/array of objects (represented by [ ]), then you will need to define your conditions as an array/list item
public List<ipAddress> conditions { get; set; }
Your assignment object for conditions should look like this,
new_rule.conditions = new List<ipAddress>() { ip_info };
This will produce the result you want. Also, According to the naming conventions, your class name and variable names should start with UpperCase letters.
For you to get your expected output, your ipAddress should be an array.
public class Rule
{
public string name { get; set; }
public ipAddress[] conditions { get; set; }
public string action { get; set; }
public Boolean enabled { get; set; }
public string statusCode { get; set; }
}
Rule new_rule = new Rule();
ipAddress ip_info = new ipAddress();
ip_info.ip = new { ipAddress = "34.5.6.7.8" };
new_rule.name = "test";
new_rule.conditions = new ipAddress[] { ip_info };
new_rule.action = "ALLOW";
new_rule.enabled = true;
new_rule.statusCode = "FORBIDDEN_403";
var rule_json = JsonConvert.SerializeObject(new_rule);
The result that u will obtain from this is
{"name":"test","conditions":[{"ip":{"ipAddress":"34.5.6.7.8"}}],"action":"ALLOW","enabled":true,"statusCode":"FORBIDDEN_403"}
You want the conditions to be an array
So you need to declare public IP addresses[] conditions
You also assigned an object to it and that's the output you get
If you want the json to have an array output you have to declare it as an array
I have a method as follows which gets data and stores them to specific variables. I also have two static variables that preserves their value if a condition is met. My question is how can I store this data in attributes in a specific class ?
Like for example, I have a class called UserDetails with attributes :
UserDetails class
public class UserDetails {
public static string RateCountry { get; set; }
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Second Class
For now, its working like this. But I want to enhance it by making use of objects.
public static string RateCountry { get; private set; }
public static string RateWeek { get; private set; }
public ActionResult ShowList()
{
int start = Convert.ToInt32(Request["start"]);
int length = Convert.ToInt32(Request["length"]);
string name = Request["search[value]"];
string address = Request[("columns[3][search][value]")];
string rateType = Request[("columns[7][search][value]")];
if (string.IsNullOrEmpty(rateType)) // if null, reset the static variables to null
{
RateCountry = "";
RateWeek = "";
}
else
{
if (CheckDate(rateType)) // if contains date, assign to RateWeek
{
RateWeek = rateType;
}
else
{
RateCountry = rateType; // else if contains a string word, assing to ratecountry
}
}
var items = AssignDetails(start, length, name, address, RateWeek, RateCountry);
return items;
}
Then instead of passing several parameters like start, length, name etc. in the method AssignDetails, I can pass an object of the UserDetails class directly taking into consideration the static variables.
Can someone please help ?
Note: In C#, they are called properties not attributes. Attributes are a totally different thing.
What you want to do is straight forward:
Firstly, you need to change your method so it accepts your class UserDetails as an argument:
public void AssignDetails(UserDetails userDetails)
{
// Use userDetails here to do whatever you want
}
Secondly, when you call the above method, you need to pass the argument to it. You can create an instance of UserDetails and pass it to the AssignDetails method:
var userDetails = new UserDetails
{
Start = start,
Length = length,
Name = name
Address = address
}
I am not sure why RateWeek, and RateCountry properties are static in your class, but to set those you can do them as below (Please note it is using the class and not the instance of the class):
UserDetails.RateWeek = RateWeek;
You could make use of the instance's properties as an indirection to the class' static properties, although all this thing is really ugly in terms of design.
public class UserDetails
{
public static string PersistedRateCountry { get; set; }
public static string PersistedRateWeek { get; set; }
public static string RateCountry
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateCountry; }
set { PersistedRateCountry = value; }
}
public static string RateWeek
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateWeek; }
set { PersistedRateWeek= value; }
}
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
I strongly suggest you to move these static properties out to another class, which would be responsible for persisting them.
E.g. try to separate your Data Object (which just holds data) from your Business Object (which contains business logic, and is constructed by receiving a Data Object as parameter). Put all that crazy persistence logic in the Business Object, and use the Business Object everywhere in your code (instead of using the Data Object).
Keep your classes short and clean. If you are coding a lot in the same class, it's probably because you got a bad object-oriented design.
I am working on a project with a lot of account management going on. Unfortunately, the guy who set all of this up is on vacation and something here needs to be done, but I cant really seem to understand what exactly is going on here ( I am kind of new to this...)
So basically, as far as I understand: When someone logs into our app, a singleton account is created. There are two classes that matter here:
namespace Accounts
{
//Generische und Lazy Singleton-Abstraktion
public abstract class AbstractAccount<T> where T : class
{
// Lazy Instanziierung
private static readonly Lazy<T> _instance = new Lazy<T>(() => CreateSingletonInstance());
public static T Instance
{
get
{
// throw new System.InvalidOperationException("out");
return _instance.Value;
}
}
private static T CreateSingletonInstance()
{
// Konstruktion des Singleton-Objekts
return Activator.CreateInstance(typeof(T), true) as T;
}
}
}
and:
class Account : AbstractAccount<Account>
{
// öffentliche Felder und Methoden
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Description { get; set; }
public List<string>Friendlist { get; set; }
public Bitmap ProfilePicutre { get; set; }
public int Experience { get; set; }
public int gender { get; set; }
public DateTime lastLogin { get; set; }
public DateTime dateCreated { get; set; }
public string Locality { get; set; }
public string Country { get; set; }
public string CountryCode { get; set; }
public int level { get; set; }
public void SetCurrentAccount(tblUsers user, DateTime lastLogin)
{
this.Username = user.getUsername();
this.Email = user.getEmail();
this.Password = user.getPassword();
this.Description = user.getdescription();
this.Experience = user.getexperience();
this.gender = user.getgender();
this.lastLogin = lastLogin;
this.dateCreated = user.getDateCreated();
this.level = CheckLevel(Experience);
}
}
Now here is the issue: When a user is login off and then creating a new account, he or she would still be set up with the properties of the user he just logged out off.
For instance: If he had 1000 xp points, then loggs off and creates a new account, that account would not start at 0 points but at 1000.
I know that his is pretty much (maybe even impossible) for you to handle from another computer but I really need help right here:
private void logoutClick(object sender, EventArgs e)
{
Context mContext = Android.App.Application.Context;
AppPreferences ap = new AppPreferences(mContext);
ap.deletePreferences();
this.FinishAffinity();
//Remove static variables. Just to be sure!
SaveAccountInfo.bpLandScapePicFull = null;
SaveAccountInfo.bpLandScapePicThumb = null;
SaveAccountInfo.bpProfilePicFull = null;
SaveAccountInfo.bpProfilePicThumb = null;
StartActivity(typeof(Activity_AcctCreationLogin));
Finish();
}
If the user was now to logout, the singleton needs to be completely destroyed and set up anew when a nother account is beeing created. I tried "Account.Instance.Dispose()"
but unfortunately, there was no such method as "dispose" after instance.
Is there any chance you guys could help me out a little? That me tremendous! Thanks so much! :)
You can set the value of your instance to a new one.
Create a method in your Account class that does this one upon logout.
_instance = new Lazy<T>(() => CreateSingletonInstance());
You should youse the Singleton pattern with these 2 methods:
public static T GetInstance
{
get
{
if (_instance == null)
_instance = new Lazy<T>(() => CreateSingletonInstance());
return _instance.Value;
}
}
public static void ReleaseInstance // called on logout
{
_instance = null;
}
also, as DavidG pointed out you should add a protected constructor.
Would it be possible for you to implement the IDisposable interface, then write your own dispose method. You could then use this method to clear the data you want cleared. Hope this helps.
In my common.cs class I have the below declarations for a list based on a class:
public static List<edbService> edb_service;
public class edbService
{
public string ServiceID { get; set; }
public string ServiceName { get; set; }
public string ServiceDescr { get; set; }
public string ServiceInterval { get; set; }
public string ServiceStatus { get; set; }
public string ServiceUrl { get; set; }
public string SourceApplication { get; set; }
public string DestinationApplication { get; set; }
public string Function { get; set; }
public string Version { get; set; }
public string userid { get; set; }
public string credentials { get; set; }
public string orgid { get; set; }
public string orgunit { get; set; }
public string customerid { get; set; }
public string channel { get; set; }
public string ip { get; set; }
}
I have a public method to populate the list from xml data files declared like this in the same class (common.cs):
#region PublicMethods
public List<edbService> populateEDBService(string xmlDataFile)
{
try
{
XElement x = XElement.Load(global::EvryCardManagement.Properties.Settings.Default.DataPath + xmlDataFile);
// Get global settings
IEnumerable<XElement> services = from el in x.Descendants("Service")
select el;
if (services != null)
{
edb_service = new List<edbService>();
foreach (XElement srv in services)
{
edbService edbSrv = new edbService();
edbSrv.ServiceID = srv.Element("ServiceID").Value;
edbSrv.ServiceName = srv.Element("ServiceName").Value;
edbSrv.ServiceDescr = srv.Element("ServiceDescr").Value;
edbSrv.ServiceInterval = srv.Element("ServiceInterval").Value;
edbSrv.ServiceStatus = srv.Element("ServiceStatus").Value;
edbSrv.ServiceUrl = srv.Element("ServiceUrl").Value;
foreach (XElement ServiceHeader in srv.Elements("ServiceHeader"))
{
edbSrv.SourceApplication = ServiceHeader.Element("SourceApplication").Value;
edbSrv.DestinationApplication = ServiceHeader.Element("DestinationApplication").Value;
edbSrv.Function = ServiceHeader.Element("Function").Value;
edbSrv.Version = ServiceHeader.Element("Version").Value;
foreach (XElement ClientContext in ServiceHeader.Elements("ClientContext"))
{
edbSrv.userid = ClientContext.Element("userid").Value;
edbSrv.credentials = ClientContext.Element("credentials").Value;
edbSrv.orgid = ClientContext.Element("orgid").Value;
edbSrv.orgunit = ClientContext.Element("orgunit").Value;
edbSrv.customerid = ClientContext.Element("customerid").Value;
edbSrv.channel = ClientContext.Element("channel").Value;
edbSrv.ip = ClientContext.Element("ip").Value;
}
}
edb_service.Add(edbSrv);
}
}
}
catch (Exception ex)
{
/* Write to log */
Common.logBuilder("CustomerCreate : Form --> CustomerCreate <--", "Exception", Common.ActiveMQ,
ex.Message, "Exception");
/* Send email to support */
emailer.exceptionEmail(ex);
}
return edb_service;
}
but the problem is, in my calling class when I try to have a list returned from this method, it is not found - I get a compile error that an object reference is required.
I am trying to call it like this:
Common.edbService edb_service = Common.populateEDBService("CardUpdate.xml");
and I get the below error:
An object reference is required for the non-static field, method, or property 'EvryCardManagement.Common.populateEDBService(string)'
What am I doing wrong?
I would like to have a generic method that can be called from several classes (which run async after being instantiated by background workers on my form)
You can try making your method as static.
public static List<edbService> populateEDBService(string xmlDataFile)
{
//Your code here
....
}
Now you can call this method from all the other classes by using common.populateEDBService();
You need either to create the class static, or to create an object to call it.
class edbService { }
public static void Main() {
//this is error
edbService.populateEDBService("");
//this is correct
edbService s = new edbService();
s.populateEDBService("");
}
The last line in my example shows the object reference required by the compiler. The s variable here is the object reference.
Are there any missing values in your XML? The.Value property won't work if the value is missing. So if ServiceID is missing then srv.Element("ServiceID").Value; will cause an error. You can get it to return an empty string for missing values, for example, by instead using (string)srv.Element("ServiceID");
I create an new Contractor object "gc" that calls a method GetContractor() to return all the properties. The results it is returning is correct, however the "gc" object shows all "NULL". I assume I doing something incorrectly in my aspx.cs page?
aspx.cs
protected void fvWasteCollected_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName.Equals("Insert")){
ValidationSummaryWasteDetail.ValidationGroup = "WasteReceivedDetail";
if (IsValid) {
odsMRWWasteCollectedDetail.InsertParameters["WasteTypeId"].DefaultValue = ddlWasteCollectedType.SelectedValue;
odsMRWWasteCollectedDetail.InsertParameters["DisposalMethodId"].DefaultValue = ddl_disposalMethod.SelectedValue;
Contractor gc = new Contractor();
gc.GetContractor(2);
var contractorName = gc.MRWContractorName;
}
}
}
.cs
public class Contractor
{
public Contractor GetContractor(int MRWContractorId)
{
using (DataAccessLINQDataContext db = new DataAccessLINQDataContext())
{
var result = db.MRWContractors.Where(c => c.MRWContractorId == MRWContractorId).Select(c => new Contractor
{
MRWContractorId = c.MRWContractorId,
MRWContractorName = c.MRWContractorName,
MRWContractorAddress = c.MRWContractorAddress,
MRWContractorCity = c.MRWContractorCity,
MRWContractorStateCode = c.MRWContractorStateCode,
MRWContractorZipCode = c.MRWContractorZipCode,
MRWContractorPhone = c.MRWContractorPhone,
MRWContractorFax = c.MRWContractorFax,
MRWContractorEmail = c.MRWContractorEmail
}).SingleOrDefault();
return result;
}
}
public int MRWContractorId { get; set; }
public string MRWContractorName { get; set; }
public string MRWContractorAddress { get; set; }
public string MRWContractorCity { get; set; }
public string MRWContractorStateCode { get; set; }
public int? MRWContractorZipCode { get; set; }
public string MRWContractorPhone { get; set; }
public string MRWContractorFax { get; set; }
public string MRWContractorEmail { get; set; }
}
You are loosing the value of gc when you dont assign it to something.
Try this instead:
var contractor = gc.GetContractor(2);
var contractorName = contractor.MRWContractorName;
You are creating one empty instance of the object that is only used to call the GetContractor method. The GetContractor method creates another instance that contains data, which is returned, but you just throw that instance away and expect the data to be available in the first instance that never got populated.
Make the GetContractor method static so that you don't need an instance to call it:
public static Contractor GetContractor(int MRWContractorId)
Now you can call the method to get that instance that contains the data, without first creating an empty instance:
Contractor gc = Contractor.GetContractor(2);
string contractorName = gc.MRWContractorName;