I'm setting up a User and Admin Permissions which works perfectly well but I want to disable some ToolStripMenuItem from "Users" but Enable them only for "Admin".
Here's the code that logs User and Admin in depending on their Roles.
if (dt.Rows[0][0].ToString() == "1")
{
if (ComboBox_LoginAs.SelectedIndex == 0)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
}
else if (ComboBox_LoginAs.SelectedIndex == 1)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
/* disable View All Employees for Users */
ViewAllEmployeesToolStripMenuItem.Enable = false;
}
I expect the Users to not be able to view all Employee Records except the Admin.
I hope this question will not get down voted.
Thank you for your help!!
Here is an example of an interface I used once that accomplishes something similar.
Main
namespace UnNamed Project
{
class Program
{
static void Main(string[] args)
{
User user;
user = new SuperUser("Bob", "12345");
if (user.Login())
{
Console.WriteLine($"Welcome {user.Name}");
}
else
{
Console.WriteLine("An error has occured.");
}
Utility.PauseBeforeContinuing();
}
}
}
Interface Class
namespace UnNamed Project
{
interface ILoginHandler
{
bool HandleLogin();
void SetPassword(string password);
}
}
User Class
namespace UnNamed Project
{
abstract class User
{
private string _name;
private int _securityLevel;
public User(string name, int securityLevel)
{
_name = name;
_securityLevel = securityLevel;
}
abstract public bool Login();
}
}
SuperUser Class
namespace UnNamed Project
{
class SuperUser : User
{
private ILoginHandler _loginHandler;
public SuperUser(string name, string password) : base(name, 10)
{
_loginHandler = new FaceLogin(password);
}
public override bool Login()
{
return _loginHandler.HandleLogin();
}
}
}
As you can see, if setup properly you can create an object "User" and another object "Admin" and then create an abstract method within user. You can alternatively do a virtual method to handle the login, just make sure that your admin class has an override for it's own Login() method. This will cause the program to use the method directly related to the object.
Okay, so I tried changing my MenuStripItem Modifier state to "public". Then I created an object on my main form.
public static Main_Form GetMainForm_Obj;
public Main_Form()
{
InitializeComponent();
}
Then inside my Form Load, I added:
private void Main_Form_Load(object sender, EventArgs e)
{
eMPLOYEESToolStripMenuItem.Enabled = true;
GetMainForm_Obj = this;
}
And finally, in my Login form:
if (ComboBox_LoginAs.SelectedIndex == 0)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
}
else if (ComboBox_LoginAs.SelectedIndex == 1)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
Main_Form.GetMainForm_Obj.eMPLOYEESToolStripMenuItem.Enabled = false;
}
Thank you everyone!
Related
I have two forms in the same namespace.
One is the main form that displays the list of accounts.
public partial class Server : Form
{
public Server()
{
InitializeComponent();
LoadAcounts();
}
public void LoadAcounts()
{
AccountDB acc = new AccountDB();
userListBox.DataSource = acc.ListUsers();
this.userListBox.SelectedIndex = 0;
}
}
Second is the registration form.
public partial class RegForm : Form
{
public RegForm()
{
InitializeComponent();
passBox.Text = "";
passBox.PasswordChar = '*';
passBox.MaxLength = 14;
passBox2.Text = "";
passBox2.PasswordChar = '*';
passBox2.MaxLength = 14;
}
private void button1_Click(object sender, EventArgs e)
{
if (passBox.TextLength >= 4 && passBox.Text == passBox2.Text && usernameBox.TextLength >= 4)
{
AccountDB acc = new AccountDB();
if (acc.UserExist(usernameBox.Text))
{
MessageBox.Show("User already exists!");
}
else
{
string user = usernameBox.Text;
string pw = PasswordHash.HashPassword(passBox.Text);
WriteDB(user, pw);
this.Close();
MessageBox.Show("Registration successful!");
//LoadAccounts();
}
}
}
}
I am currently stuck on how can I call LoadAccounts() after Registration successful so the userListBox will be refreshed to include the newly added account.
I am not sure about your design, but you can create an instance property of the "Server" class in your "RegForm" class. BUT, I should say that is increasing class coupling and definitely is not a good pattern.
public partial class RegForm : Form
{
public Server serverFormInstance {get; set;}//must be filled from caller code
...
...
If you have only one instance of the Server form, you can make it as a singleton to be able to call the method.
public class Server : Form
{
static internal readonly Server Instance = new Server ();
private Server()
{
InitializeComponent();
LoadAcounts();
}
}
Or any singleton implementation you like.
So you'll change all access to Server by Server.Instance.
Now you can call:
Server.Instance.LoadAcounts();
But if you plan to allow several instances of Server, a registration method may be used but it requires more code of your project to think about that.
You can also read this:
Communicate between two windows forms in C#
I have a class called currentUser and another called game. from game, i am trying to access a variable from currentUser, I know for sure that the variable is created and it contains something in currentUser before i call it in game but i get an empty string. What am i doing wrong here. here is what i have
public class currentUser
{
private string currentUser;
public string getCurrentUser
{
get {return currentUser;}
set {currentUser = value;}
}
//this gets pushed in the beginning of the program
private void btn_click(object sender, RoutedEventArgs e)
{
currentUser = txtUsername.Text;
}
}
public class game
{
currentUser myCurrentUser = new currentUser();
string var = myCurrentUser.getCurrentUser();
//this is another method being called in another class, but i dont think it is relevant. by the time i step over to here, var is null.
clsScores.getScore(25, var);
}
i have tried looking, but this is the same example i see, so i don't know why it would not be working.
Try this: (I don't know how you are calling the code in Game, so I've just called it in a method DoSomething). If you get the result "No name", that means there's a problem with getting the user from the textbox.
public class CurrentUser
{
private string _user;
public string User
{
get { return _user; }
set { _user = value; }
}
//this gets pushed in the beginning of the program
private void btn_click(object sender, RoutedEventArgs e)
{
if(String.IsNullOrEmpty(txtUsername.Text)
{
_user = "No name";
}
else
{
_user= txtUsername.Text;
}
}
}
public class Game
{
public void DoSomething()
{
var myCurrentUser = new CurrentUser();
var user = myCurrentUser.User;
Console.WriteLine(user);
}
}
You have accidentally put parenthesis in:
string var = myCurrentUser.getCurrentUser();
Remove them because "getCurrentUser" is a property, not a method. Properties do not need parenthesis.
Ontop of a lot of other problems mentioned unless you are setting "currentUser" in the time between "currentUser myCurrentUser = new currentUser();" and "string var = myCurrentUser.getCurrentUser();". Your variable will never get set.
Im making a program what connects to multiple 3th party systems. The connect with different formats so i created multiple classes to deal with them. I have now three 4 classes.
The MainForm is the first class. This is the basic windows form class with the user interface.
SDKCommunication is the second class.
VMS (this class handles the events given of by the 2th party system and activates methods on SDK COmmunication)
Events
Events Class
public class Events
{
public event EventHandler LoginStateChanged;
private bool loginstate;
public bool LogInState
{
get { return this.loginstate; }
set
{
this.loginstate = value;
if (this.LoginStateChanged != null)
this.LoginStateChanged(this, new EventArgs());
}
}
}
part of SDKCommunicatie class
Events events = new Events();
public void onLogon(string username, string directory, string system)
{
events.LogInState = false;
}
MainForm Class
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
Events events = new Events();
public MainForm()
{
InitializeComponent();
events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
log.Info("EventFired loginstateChanged");
}
When the LogInState Changes in the SDKCommunicatie class. There needs to be an event fired in the MainForm class. But sadly that doesn't work.
But when I change the loginstate in the mainform(with a buttonclick)(see code below) the event is fired. But that is not the intention i would like to have.
private void button1_Click(object sender, EventArgs e)
{
events.LogInState = true;
}
If my question isn't clear enough, please let me know.
VMS class Added as reply to #Astef
class VMS {
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(MainForm));
GxUIProxyVB m_UIProxy = new GxUIProxyVB();
public string username2;
public string directory2;
public string Status;
public void initOmni()
{
m_UIProxy.CreateInstance();
m_UIProxy.OnLogon += new _IGxUIProxyVBEvents_OnLogonEventHandler(m_UIProxy_OnLogon);
m_UIProxy.OnLogoff += new _IGxUIProxyVBEvents_OnLogoffEventHandler(m_UIProxy_OnLogoff);
m_UIProxy.OnError += new _IGxUIProxyVBEvents_OnErrorEventHandler(m_UIProxy_OnError);
m_UIProxy.OnAlarmStatusEx2 += new _IGxUIProxyVBEvents_OnAlarmStatusEx2EventHandler(m_UIProxy_OnAlarmStatusEx2);
}
public void login(string username, string password, string directory)
{
username2 = username;
directory2 = directory;
initOmni();
m_UIProxy.LogOn(directory, username, password,false);
}
public void logOff()
{
m_UIProxy.LogOff();
}
void m_UIProxy_OnLogon()
{
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
sdkcommunicatie.onLogon(username2, directory2, "Genetec Omnicast");
}
I have fixed this with deleting the following:
SDKCommunicatie sdkcommunicatie = new SDKCommunicatie();
And adding the following in the base of VMS:
SDKCommunicatie sdkcommunicatie;
But now i got a new error in the mainform when i tried to call a class in SDKCommunicatie
connectedStatus = sdkcommunicatie.connectedStatus();
I got the following error:
NullReferenceException was unhandled
You are not using the same instance of the Events class, and that's why on button click you catch LoginStateChanged. You should inject the same instance of Events class to SDKCommunicatie class, then you'll be able to listen to event changes.
Edit:
Jeremy Todd and I were both writing at the same time.
Events in your SDKCommunicatie are not fired because you've created an individual instance of class Events for it. That is not the instance you have placed on the MainForm.
Inject the right instance (pass a reference) to SDKCommunicatie from MainForm through constructor, property or somehow else. For example:
MainForm:
SDKCommunicatie sdkcommunicatie;
Events events = new Events();
public MainForm()
{
InitializeComponent();
events.LoginStateChanged += new EventHandler(events_LoginStateChanged);
sdkcommunicatie = new SDKCommunicatie(events);
}
void events_LoginStateChanged(object sender, EventArgs e)
{
log.Info("EventFired loginstateChanged");
}
SDKCommunicatie:
Events events;
public SDKCommunicatie(Envents eventsInstance)
{
events = eventsInstance;
}
public void onLogon(string username, string directory, string system)
{
events.LogInState = false;
}
Your SDKCommunication class and your MainForm class each have their own separate instance of Events, so any events you trigger from one won't be visible from the other -- they're being raised on an entirely different object.
What you need is a single instance of the Events class that both SDKCommunication and MainForm can share -- that way they'll both be seeing the same thing. There are several different approaches you could take for this. Depending on what it needs to do, one very simple possibility might be to make Events a static class, and then the events would be visible everywhere without needing to create any instances.
I have solved the riddle.
When i need a method is a class i can call the method directly like this:
public class MainForm : Form
{
SDKCommunication sdkcommunication = new SDKCommunication();
public MainForm()
{
}
private void Button1_Click(oject sender, EventArgs e)
{
sdkcommunication.method("Test")
}
}
This is pretty straightforward. Look here the receiverclass:
public class SDKCommunication
{
method(string word)
{
//do something with word
}
}
The biggest problem is calling the class with the form(the original class). I have solved this with a eventhandler.
class CustomEventHandler1 : EventArgs
{
public CustomEventHandler1(string u, string d)
{
msgu = u;
msgd = d;
}
private string msgu;
private string msgd;
public string Username
{
get { return msgu; }
}
public string Directory
{
get { return msgd; }
}
}
Then the SDKCOmmunication class should look like this:
class SDKCommunication
{
public event EventHandler<CustomEventHandler1> RaiseCustomEventHandler1;
protected virtual void OnRaiseCustomEventHandler1(CustomEventHandler1 e)
{
EventHandler<CustomEventHandler1> handler = RaiseCustomEventHandler1;
if (handler != null)
{
handler(this,e);
}
}
//Custom Method that is called somewhere
internal void custommethod()
{
OnRaiseCustomEventHandler1(new CustomEventHandler1("johnsmith", "localhost");
}
}
Then in the mainform class:
public class MainForm : Form
{
public MainForm()
{
sdkcommunication.RaiseCustomEventHandler1 += new EventHandler<CustomEventHandler1>(sdkcommunication_RaiseCustomEventHandler1);
}
void sdkcommunication_RaiseCustomEventHandler1(object sender, CustomEventHandler1 e)
{
//Do something.
}
}
The information sended with the event you can get with e.Username and e.Directory. In this example they are strings where e.Username = johnsmith and e.Directory = localhost.
I hope somebody can use this information for their own code.
How to avoid multiple instances of windows form in c# ?? i want only one instance of the form running. Because there are chances of opening the same form from many pages of my application.
implement the Singleton pattern
an example: CodeProject: Simple Singleton Forms (ok, it's in VB.NET, but just to give you a clue)
Yes, it has singleton pattern,
Code to create a singleton object,
public partial class Form2 : Form
{
.....
private static Form2 inst;
public static Form2 GetForm
{
get
{
if (inst == null || inst.IsDisposed)
inst = new Form2();
return inst;
}
}
....
}
Invoke/Show this form,
Form2.GetForm.Show();
When you display the dialog simply use .ShowDialog(); instead of .Show();
One solution I applied to my project in order to bring this form again in the foreground is:
private bool checkWindowOpen(string windowName)
{
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (Application.OpenForms[i].Name.Equals(windowName))
{
Application.OpenForms[i].BringToFront();
return false;
}
}
return true;
}
windowName is essentially the class name of your Windows Form and
return value can be used for not creating a new form instance.
If your system has the possibility of showing the same type of form for different instance data then you could create a checking system that iterates all existing open forms, looking for a unique instance data identifier and then re-display any found form.
e.g. having a form class 'CustomerDetails' which contains a public property 'CustomerUniqueID':
foreach(Form f in CurrentlyDisplayedForms)
{
CustomerDetails details = f as CustomerDetails;
if((details != null) && (details.CustomerUniqueUD == myCustomerID))
{
details.BringToFront();
}
else
{
CustomerDetails newDetail = new CustomerDetails(myCustomerID);
}
}
We also use the same mechanism to automatically force refreshes of data binding where a customer's data has been edited and saved.
Here is my solution in ShowForm() :
private void ShowForm(Type typeofForm, string sCaption)
{
Form fOpen = GetOpenForm(typeofForm);
Form fNew = fOpen;
if (fNew == null)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
else
if (fNew.IsDisposed)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
if (fOpen == null)
{
fNew.Text = sCaption;
fNew.ControlBox = true;
fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
fNew.MaximizeBox = false;
fNew.MinimizeBox = false;
// for MdiParent
//if (f1.MdiParent == null)
// f1.MdiParent = CProject.mFMain;
fNew.StartPosition = FormStartPosition.Manual;
fNew.Left = 0;
fNew.Top = 0;
ShowMsg("Ready");
}
fNew.Show();
fNew.Focus();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
ShowForm(typeof(FAboutBox), "About");
}
private Form GetOpenForm(Type typeofForm)
{
FormCollection fc = Application.OpenForms;
foreach (Form f1 in fc)
if (f1.GetType() == typeofForm)
return f1;
return null;
}
private object CreateNewInstanceOfType(Type typeofAny)
{
return Activator.CreateInstance(typeofAny);
}
public void ShowMsg(string sMsg)
{
lblStatus.Text = sMsg;
if (lblStatus.ForeColor != SystemColors.ControlText)
lblStatus.ForeColor = SystemColors.ControlText;
}
check this link :
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
Try this code
Public class MyClass
{
//Create a variable named
public static int count = 0;
//Then increment count variable in constructor
MyClass()
{
count++;
}
}
While creating the object for the above class 'MyClass' check the count value greater than 1
class AnotherClass
{
public void Event()
{
if(ClassName.Count <= 1)
{
ClassName classname=new ClassName();
}
}
}
Here's a simple way to do it.
Check if the form is null, or has been disposed. If that's true we create a new instance of the form.
Otherwise we just show the already running form.
Form form;
private void btnDesktop_Click(object sender, EventArgs e)
{
if (form == null || desktop.IsDisposed)
{
form = new Form();
form.Show();
}
else
{
form.WindowState = FormWindowState.Normal;
}
}
private static MyForm _myForm;
internal static MyForm form
{
get
{
if (_myForm == null)
{
_myForm = new MyForm();
}
return _myForm;
}
}
public MyForm()
{
InitializeComponent();
_myForm = this;
}
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
_myForm = null;
}
Singletons are not object-oriented. They are simply the object version of global variables. What you can do is to make the constructor of the Form class private, so nobody can accidentally create one of these. Then call in reflection, convert the ctor to public and make sure you create one and only one instance of it.
You can check the existing processes prior to opening the form:
using System.Diagnostics;
bool ApplicationAlreadyStarted()
{
return Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length == 0;
}
I don't know if the GetProcessesByName method is affected by UAC or other security measures.
I have an object that handles the logging in of users. This object has a method called LoginPopUp(), which calls Login.show() to display the Login form/window.
The form/window is a seperate object. When a user enters their details and presses submit I want the form to pass data BACK to the calling object. The calling object (the object that handles loging in) will then validate the username and password. If the user is in the database it will close the window.
If the user is not in the database it will remain open and display "incorrect login". So I need a way for the calling object to pass information back to the login window to tell it it's failed.
Im a little confused on how to do this. Is this a case for callbacks and delegation? Whats the conventional solution to use in cases like this? As I'd imagine this happens a lot.
Comments appreciated.
You can do this with a delegate (aka callback). Have a delegate typed property of the login form that the caller can set. You can also do it with an event (which is also a delegate really) and have the login form expose an event that the caller can subscribe to before showing the form.
However, if the same action is always taken after login, then it might be more straightforward to do a direct call instead of using delegates.
Your approach will work.
Another simple option is to pass a reference to the user validator to the login window
make the validation function static.
to do what you want here is an ex.
Just create form1 with a text box and form2 with two text boxes and a button to run.
namespace TestApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public bool DoValidate(string username, string password)
{
MessageBox.Show(string.Format("I got called with {0} : {1}",username,password));
return true;
}
private void button1_Click(object sender, EventArgs e)
{
Form2 F = new Form2(DoValidate);
F.ShowDialog();
}
}
}
namespace TestApp
{
public partial class Form2 : Form
{
private Form2()
{
InitializeComponent();
}
public delegate bool LoginFn(string Uname, string pword);
private LoginFn m_CallFn;
public Form2(LoginFn del)
{
InitializeComponent();
m_CallFn = del;
}
private void cmdLogon_Click(object sender, EventArgs e)
{
if (!m_CallFn(txtUser.Text, txtPassword.Text))
{
MessageBox.Show("Fail");
}
else
{
MessageBox.Show("Good");
}
}
}
}
You could achive this in multiple ways
using delegate callbacks
using func delegate(inline anonymos methods)
using events
public class FormTest:Form
{
public delegate int validateLogin(string userID,string Password);
public validateLogin validate;
public event validateLogin validateEvent;
public void submitWithcallback()
{
string userId=string.Empty,pwd=string.Empty;
validate(userId, pwd);
}
public void submitWithFuncDelegate(Func<string,string,int> funcDelegate)
{
string userId = string.Empty, pwd = string.Empty;
funcDelegate(userId, pwd);
}
public void submitWithEvent()
{
string userId = string.Empty, pwd = string.Empty;
validateEvent(userId, pwd);
}
}
and invoke this from your class
public class Test
{
static int validate(string uid, string pwd)
{
//your validation code
return 1;
}
void testValidate()
{
Func<string, string, int> validateFunc = (uid, pwd) =>
{
//your validation code
return 1;
};
FormTest.validateLogin vDel = new FormTest.validateLogin(validate);
FormTest v1 = new FormTest();
v1.validate = new FormTest.validateLogin(vDel);
v1.submitWithcallback();
v1.submitWithFuncDelegate(validateFunc);
v1.validateEvent += new FormTest.validateLogin(validate);
//or with anonymous functions
v1.validateEvent += (string uid,string pwd)=>{
//your validation code
return 1;
};
v1.submitWithEvent();
}
}
expose event on Login form, like LoginSubmitted with event args that contain the login and password
expose method on Login form, like ShowLoginFailed()
subscribe to the LoginSubmitted event in the controlling object, and handle it by reading the login and password from the event args and checking the database
if login is successful, close Login, otherwise call ShowLoginFailed()
Callback/closures will work well here.
Maybe a snippet will help explain.
bool CheckUser(string user, string pass) { ... }
...
void ShowLogin(Func<string,string,bool> check)
{
var f = new LoginForm();
f.LoginClick += delegate
{
if (check(f.User, f.Pass))
{
f.Close();
}
};
f.ShowDialog();
}
Usage:
ShowLogin(CheckUser);