I am really stuck on calling my function InlogLeerling() from .cs file Login.cs into MainPage.xaml.cs.
I did try everything and I already found some answers but I do not understand how I can get it working in my project. When i call the function InlogLeerling() I get the error There is no argument given that corresponds to the required formal parameter 'mainpage' of 'Login.InlogLeerling(MainPage)'
Here is the code I am using in my Login.cs
namespace VerlofXamarin.Logical_Layer
{
public class Login
{
public string pu_Gebruikersnaam, pu_Wachtwoord, pu_LogLeerling;
string Gebruikersnaam
{
get { return pu_Gebruikersnaam; }
set { pu_Gebruikersnaam = value; }
}
string Wachtwoord
{
get { return pu_Wachtwoord; }
set { pu_Wachtwoord = value; }
}
public MainPage mainpage;
private void InlogLeerling(MainPage mainpage)
{
Data_Layer.Verbinding vv = new Data_Layer.Verbinding();
this.mainpage = mainpage;
try
{
if(string.IsNullOrEmpty(pu_Gebruikersnaam) == true || string.IsNullOrEmpty(pu_Wachtwoord) == true)
{
mainpage.pu_LeerlingLog = "Vul gebruikersnaam en wachtwoord in!";
return;
}
vv.con.Open();
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand("SELECT leerlinggebruikersnaam, leerlingwachtwoord FROM arabignl_project.myfirstmodule$leerlinglogin WHERE (leerlinggebruikersnaam = #gebruiker AND leerlingwachtwoord = #wachtwoord)", vv.con);
cmd.Parameters.AddWithValue("#gebruiker", pu_Gebruikersnaam.ToString());
cmd.Parameters.AddWithValue("#wachtwoord", pu_Wachtwoord.ToString());
MySqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
mainpage.pu_LeerlingLog = "Inloggen gelukt";
}
}
else
{
mainpage.pu_LeerlingLog = "Inloggen mislukt";
}
reader.Close();
}
catch (MySqlException ex)
{
mainpage.pu_LeerlingLog = ex.ToString();
}
finally
{
vv.con.Close();
}
}
}
}
And the MainPage.xaml.cs
namespace VerlofXamarin
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
public Login login;
public string pu_LeerlingLog
{
get { return LoginLog.Text; }
set { LoginLog.Text = value; }
}
public string pu_LeerlingGebruikersnaam
{
get { return LeerlingGebruikersnaam.Text; }
}
public string pu_LeerlingWachtwoord
{
get { return LeerlingWachtwoord.Text; }
}
public void LoginKlik(Login login)
{
this.login = login;
login.InlogLeerling();
}
I have already tried so many things.
You have two problems in your code.
You can´t call any private member from outside your class. So make your method public
your method expects a parameter of type MainPage. So you have to provide it, which is exactly what your error states:
public void LoginKlik(Login login)
{
this.login = login;
login.InlogLeerling(this);
}
Apart from those you shouldn´t expose a field publicily. Instead use a public property which you can modify within your class and read outside your class Login:
public MainPage MainPage { get; private set; }
You should study access modifier. With private, other classes could not access it. So you could change it to either internal or public. Here is reference
- https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/access-modifiers
internal void InlogLeerling(MainPage mainpage)
You will not be able to call the method because they are not in same class.
When you give an access modifier of privte, the accesses is possible only within the class.
If you would like to give more access there is:
protected - A protected member is accessible within its class and by derived class instances.
Internal- Internal types or members are accessible only within files in the same assembly.(i.e. the same compiled program)
public- . Public access is the most permissive access level. There are no restrictions
Therefor by using internal or public (depends on what you need in more large aspect) you will be able to access this method within other classes in your project
Related
I have code like below. Interface with default implementation. And the user who uses this interface. But for some reason in the switch case my code uses the default implementation of the interface for the "Name' instead of the class implementation. What should i change to see "Ben" in console?
namespace ConsoleApp1
{
public interface IUser
{
// Interface with default implementation
public string Name { get => "Tom"; }
}
// User using this interface
public class BenUser : IUser
{
public string Name = "Ben";
}
public static class MainClass
{
public static void ShowName(IUser user)
{
switch (user.Name)
{
case "Ben": // I expected the code to run here
Console.WriteLine("Ben");
break;
case "Tom": // But the code goes here
Console.WriteLine("Tom");
break;
}
}
static void Main()
{
// Create a user with Name "Ben"
var ben = new BenUser();
ShowName(ben); // In console i see "Tom" for some reason
}
}
}
I can't figure out why the code is behaving like this.
As mentioned in comments, you need to implement the interface using the same shape in your class - as a property with a get.
public interface IUser
{
// Interface with default implementation
public string Name { get => "Tom"; }
}
// User using this interface
public class BenUser : IUser
{
public string Name { get => "Ben"; }
}
public static class MainClass
{
public static void ShowName(IUser user)
{
switch (user.Name)
{
case "Ben": // I expected the code to run here
System.Console.WriteLine("Ben");
break;
case "Tom": // But the code goes here
System.Console.WriteLine("Tom");
break;
}
}
static void Main()
{
// Create a user with Name "Ben"
var ben = new BenUser();
ShowName(ben); // In console i see "Tom" for some reason
}
}
This is my edit to show some more standard practices, please read through the comments and see if it makes anything more clear. The standard practice for creating members is to use accesslevel Type VariableName { get; set; }
namespace ConsoleApp1
{
public interface IUser
{
//denotes that this is set by construction, cannot be set afterwards
public string Name { get; }
}
// User using this interface
public class BenUser : IUser
{
// Standard 'getter' only member with a compiled return value
public string Name
{
get
{
return "Ben";
}
}
}
public class User : IUser
{
// private settable string to use with construction
private string _name;
// constructor
public User(string userName)
{
// sets the private variable to desired value
_name = userName;
}
// public 'getter' that returns the set value
public string Name
{
get
{
return _name;
}
}
}
public static class MainClass
{
public static void ShowName(IUser user)
{
Console.WriteLine(user.Name);
}
static void Main()
{
// Create a user with static Name "Ben"
var ben = new BenUser();
ShowName(ben);
// Create a user with variable Name set as "Carl"
var carl = new User("Carl");
ShowName(carl);
}
}
}
The Name in IUser is a property while Name in BenUser is a field. With your code when we do user.Name it calls the get method defined in IUser instead of getting value of Name field from BenUser. Here is a sample implementation for fixing your bug.
public class BenUser : IUser
{
public string Name { get => "Ben"; }
}
I would recommend to not do it the way you are doing because Name identifier has become embiguos
I am not sure that this title is correct..Anyways I have a class that has a number of methods that control a stereo. Each method will send a command to a serial port. There are many models of stereos supported and each stereo may have a different command that needs to be sent.
For example model_A may need to send the command "VOLUP" to the serial port and "model_B" may need to send the command "GAINUP" to increase the volume. I want to have one method called IncreaseVolume like this:
public void IncreaseVolume()
{
serialPort.WriteLine(volumeCommand);
}
This method will be called from another class after setting the model of the radio. Now for two radios I could do this:
public class StereoControl
{
string volumeCommand;
string model_A_Volume_Command = "VOLUP";
string model_B_VOlume_Command = "GAINUP";
public void Set_Radio_Model(string model)
{
if (model == "modelA")
{
volumeCommand = model_A_Volume_Command;
}
else if (model == "modelB")
{
volumeCommand = model_B_Volume_Command;
}
}
public void IncreaseVolume(volumeCommand)
{
serialPort.WriteLine(volumeCommand);
}
}
So the main program will first set the model and then anytime the volume needs increasing it will just call the IncreaseVolume method.
The things is that there are potentially dozens of stereos and dozens of commands and I don't necessarily want all these in if then or case statements.
I thought of creating structures for each model containing the commands but then how do you select which structure to use in the methods?
I am sure there is a more elegant way to do this and am open to suggestions.
The first answer while usable, when we get 100+ commands and 200+ stereo's it will be a bit too difficult to handle. So here is another possibility but I do not know how to get the class reference available throughout the application.
public Class Model_A
{
string volumeCommand = "VOLUP";
}
public Class Model_B
{
string volumeCommand = "GAINUP";
}
public Class StereoControl
{
public void Set_Radio_Model(String model)
{
if (model == "model_a")
{
var _radio = new Model_A();
}
else if (model == "model_b")
{
var _radio = new Model_B();
}
}
public void IncreaseVolume()
{
serialPort.WriteLine(_radio.volumeCommand);
}
}
Of course the issue here is that the scope of _radio is only within the Set_Radio_Model. Is there a way to _radio usable everywhere?
Tom
The very basic way is to have Enum of stereos names and then implement it in OOP
(I hope people help to improve it) this is just depends on my opinion.
1- Define enum like:
public enum StereoBrand
{
Stero1 = 0,
Stereo2 = 1
}
2- Define an interface to enforce all stereos implement IncreaseVolume() like:
public interface IStereo
{
string VolumeCommand { get; }
string SteroeName { get; }
void IncreaseVolume();
}
by above interface each stereo should have a name as StereoName.
3- And then implement StereoController like :
public class SteroController : IStereo
{
public virtual string SteroeName
{
get
{
return string.Empty;
}
}
public virtual string VolumeCommand
{
get
{
return string.Empty;
}
}
public virtual void IncreaseVolume()
{
throw new NotImplementedException();
}
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
switch (brand)
{
case StereoBrand.Stero1:
stereo = new Stereo1();
break;
case StereoBrand.Stereo2:
stereo = new Stereo2();
break;
}
return stereo;
}
}
Notes of Step3:
3.1- StereoController implement IStereo and change that prop and Increase method to Virtual that all Stereo can override them.
3.2- GenerateStereo which create related stereo by its StereoName
4- Suppose we have to implement Stereo classes here Stereo1 and Stereo2 like:
public class Stereo1 : SteroController
{
public override string SteroeName
{
get
{
return "Streo1";
}
}
public override string VolumeCommand
{
get
{
return "Command1";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand
}
public Stereo1()
{
}
}
public class Stereo2 : SteroController
{
public override string SteroeName
{
get
{
return "Streo2";
}
}
public override string VolumeCommand
{
get
{
return "Command2";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand2
}
public Stereo2()
{
}
}
5- The last step is using them like:
var stero = SteroController.GenerateStereo((StereoBrand)Enum.Parse(typeof(StereoBrand), "brandName"));
stero.IncreaseVolume();
Notes:
N1: This is better to implement GenerateStereo by reflection which means find all IStereo and make an instance by reflection.
N2: The another solution to avoid switch-case is using reflection to find related Stereo like:
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
var type = typeof(IStereo);
var types = AppDomain.CurrentDomain.GetAssemblies()//Find all classes which implemented ISereo
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p)).ToList();
foreach(Type t in types)
{
var stereoNameProp = t.GetProperties().SingleOrDefault(p => p.Name == "StereoName");//Get stereo name prop
if (stereoNameProp != null && stereoNameProp.GetValue(t).ToString() == brand.ToString())//Check it with brand name
stereo =(SteroController)Activator.CreateInstance(type);//Make an instance
}
return stereo;
}
Hope it help and give you the clue.
This question already has answers here:
Inconsistent Accessibility: Parameter type is less accessible than method
(13 answers)
Closed 5 years ago.
My project has 3 classes. A form class with a textbox and a datetimepicker, a class called BuildingPermit and a class called Validator.
I'm using the Validator class to have handle generic data validation such as throwing an error whether or not the text box is blank or has enough characters.
I'd also like like to create a method in the Validator class that compares the values in the text box to a list of values to see if it already exists. I've written the method below and I'm getting an inconsistent accessibility error.
Can you please help me understand why I'm still getting the error when I change the building permit class access to internal? Or would I have to handle the validation directly in the form?
Thanks
public static bool IsUniquePermit(TextBox textbox, List<BuildingPermit> buildingPermitList)
{
foreach (BuildingPermit bp in buildingPermitList)
{
if (textbox.Text == bp.permitNo)
{
MessageBox.Show("That permit number has been previously issued");
return false;
}
else
{
return true;
}
}
}
For reference, the BuildingPermit class is below.
class BuildingPermit
{
DateTime _issuanceDate;
string _permitNo;
public BuildingPermit(DateTime issuanceDate, string permitNo)
{
_issuanceDate = issuanceDate;
_permitNo = permitNo;
}
public DateTime issuanceDate
{
get
{
return _issuanceDate;
}
set
{
_issuanceDate = value;
}
}
public string permitNo
{
get
{
return _permitNo;
}
set
{
_permitNo = value;
}
}
}
}
The default class access level is internal if not specified. Assuming that the class that has the IsUniquePermit method is public, then you're exposing the BuildingPermit class as part of your public API, but the class isn't available. Short answer is to make BuildingPermit public.
More info about it is here: https://stackoverflow.com/a/2521492/149436
You can create an Interface, that is public and keep the class internal.
public interface IBuildingPermit
{
public DateTime issuanceDate
{
get;
set;
}
public string permitNo
{
get;
set;
}
}
Implement it to your class:
class BuildingPermit : IBuildingPermit
{
DateTime _issuanceDate;
string _permitNo;
public BuildingPermit(DateTime issuanceDate, string permitNo)
{
_issuanceDate = issuanceDate;
_permitNo = permitNo;
}
public DateTime issuanceDate
{
get
{
return _issuanceDate;
}
set
{
_issuanceDate = value;
}
}
public string permitNo
{
get
{
return _permitNo;
}
set
{
_permitNo = value;
}
}
}
And change the Method like this:
public static bool IsUniquePermit(TextBox textbox, List<IBuildingPermit> buildingPermitList)
{
foreach (IBuildingPermit bp in buildingPermitList)
{
if (textbox.Text == bp.permitNo)
{
MessageBox.Show("That permit number has been previously issued");
return false;
}
else
{
return true;
}
}
}
I want to transfer this part of java code to C# but I have get stucked in that:
public class PCComm {
private SerialConnection sc;
public String systemfaults() {
if ( (sc == null) || !sc.open) {
return ("Serial communication not established");
}
return ("OK");
}
}
The Error for the (!sc.open) is that : Serialconnection.open is inaccessible due to its protection level
I changed the "Private" access level to "protected" level. Does it make sense ?
Edition:
I changed the code based on the comments that I got:
public class PCComm {
public readonly static int OPEN = 0;
private SerialConnection sc;
public PCComm() {
}
public String systemfaults() {
if ( (sc == null) || !sc.open) {
return ("Serial communication not established");
}
return ("OK");
}
}
Still I get error in (sc.open)...
No, protected will not make the fields of SerialConnections available to external classes. You can either make the open field public:
public boolean open
or define a method, like this:
public boolean isOpen(){
return this.open;
}
I'm using the Singleton design pattern and I must return the object if it hasn't been used before.
I get an exception in the following code :
namespace app.Models
{
public class Conexion:DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get {//error here
if (Instance == null)
{
Instance = new Conexion(#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
public void SaveChanges()
{
MainConexion.SaveChanges();
}
}
}
How can I solve this?
Remove the override of the SaveChanges method:
namespace app.Models
{
public class Conexion : DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get
{ //error here
if (Instance == null)
{
Instance = new Conexion(
#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
}
}
Since you have a private constructor, the only instance of this class that can be used is the one exposed in the MainConexion property. It looks like you were trying to make sure that when any instance's SaveChanges method was called that the SaveChanges method on the MainConnection property's instance was called. This is not necessary, because you can only ever have one instance of the Conexion class, and it's the instance that you want to call SaveChanges on. The usage is still the same:
Conexion.MainConexion.SaveChanges();
That being said, I think you would have better luck if you were to not implement it this way. It would probably be better to open and close connections as they were needed, rather than rely on a single connection instance. What happens if the connection is interrupted? Rather than getting a single error, your application will be broken.