ASP.NET call button action from different class - c#

I have a class Lot with a function AddPiece(piece).
I also have a Page with a button btnPanel that on click fires the function
public void btnPanel_OnClick(object sender, EventArgs e){}
I want to call the btnPanel_OnClick from the Addpiece function but when I try to do it it does not show in the intlliSense and I get this compilation error "The name 'btnPanel_OnClick' does not exist in the current context". Both classes are in the same namespace. Is this possible?
Here is what I have:
namespace GraphicW_Array
{
public partial class Board : System.Web.UI.Page
{
public void btnPanel_OnClick(object sender, EventArgs e)
{
...code...
}
}
}
and
namespace GraphicW_Array
{
public class Lot
{
public void addPiece(int piece)
{
lotPresent[lotLoad] = piece;
lotLoad++;
}
}
}

I think the answer is yes you can but you probably don't want to. To call the method you need and instance of your page class so you could do
namespace GraphicW_Array
{
public class Lot
{
public void addPiece(int piece)
{
lotPresent[lotLoad] = piece;
lotLoad++;
var myPage = new Board();
myPage.btnPanel_OnClick(null,EventArgs.Empty);
}
}
}
But what would that actually do? I have no idea because you haven't posted the code but i suspect it won't do anything useful for you.
What are you actually trying to achieve?
Maybe this is want you want
namespace GraphicW_Array
{
public class Lot
{
public void addPiece(int piece, Board myPAge)
{
lotPresent[lotLoad] = piece;
lotLoad++;
myPage.btnPanel_OnClick(null,EventArgs.Empty);
}
}
}
Then in your page you can call it like this:
var myLot = new Lot();
myLot.addPiece(4,this);

Yes, this is possible.
Ensure your Lot class has a reference to the Board class in order to be able to call it, or define an event on it that the Board class can subscribe to and that will call this mathod when the event fires.
If you don't use the sender and e parameters, just pass a null and EventArgs.Empty.

You can call page's event by passing either null(if sender and EventArgs is not mandatory) but below is the better way to go.
It is not wise and not good practice to call a event from a class, however you can create another method with arguments in your class and then call it with desired parameters when it is needed.
This is can be accomplished as below:
Say you have below event
public void btnPanel_OnClick(object sender, EventArgs e)
{
//Do some common tasks to do here
}
Rearrange it as below:
public void btnPanel_OnClick(object sender, EventArgs e)
{
Lot lot = new Lot();
lot.CommonFunction(arg1, arg2); // Pass required data
}
public class Lot
{
public void AFunction()
{
//Do something
//...
CommonFunction(arg1, arg2); // Pass required data
//...
//Do something
}
public void CommonFunction(string arg1, string arg2)
{
// Do some common tasks to do here
}
}

Related

How to transfer or get values from 1 user control to/from other user control.cs

I want to transfer values from here
public partial class Burger : UserControl
{
public int t_num_Z_bur = 0;
public int t_num_B_bur = 0;
mol md = new mol();
private void button1_Click(object sender, EventArgs e)
{
t_num_Z_bur++;
md.my(180);
md.sou = "180";
textBox1.Text = t_num_Z_bur.ToString();
}
}
And this the user control from here I get the values and make changes in textbox 1. How it could change the values?
public partial class mol : UserControl
{
public string sou
{
set { textBox1.Text = value; }
}
public void my (int value)
{
textBox1.Text = value.ToString();
}
}
Please help me out
Thanks in advance
The best way to deal with communication between containers is to implement an observer class
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
(Wikipedia)
the way i do this is creating an Observer class, and inside it write something like this:
1 public delegate void dlFuncToBeImplemented(string signal);
2 public static event dlFuncToBeImplemented OnFuncToBeImplemented;
3 public static void FuncToBeImplemented(string signal)
4 {
5 OnFuncToBeImplemented(signal);
6 }
so basically: the first line says that there would be a function that somebody else will implement
the second line is creating an event that occurs when the delegated function will call
and the third line is the creation of the function that calls the event
so in your UserControl, you should add a function like this:
private void ObserverRegister()//will contain all observer function registration
{
Observer.OnFuncToBeImplemented += Observer_OnFuncToBeImplemented;
/*and more observer function registration............*/
}
void Observer_OnFuncToBeImplemented(string signal)//the function that will occur when FuncToBeImplemented(signal) will call
{
MessageBox.Show("Signal "+signal+" received!", "Atention!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
and in your Form you should do something like:
public static int signal = 0;
public void button1_Click(object sender, EventArgs e)
{
Observer.FuncToBeImplemented(signal);//will call the event in the user control
}
and now, you can register this function to a whole bunch of other controls and containers and they will all get the signal
I hope this would help :)

Update label through another class

I'm trying to call method Run in script1. Then from script1 call method alert or wait and try to update statusLabel in Form1. But this code has an error.
static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
This code will only work in Form1. Because this return error in another classes. Maybe it is not correct and you know better solution.
P.S. I know how to solve this problem (see below "Not the best solution"), but the code will be ~ 10-30 new lines.
Project
Form1.cs
public partial class Form1 : Form
{
private void statusLabel_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
script1.Run();
...
script30.Run();
}
}
function.cs (Frequently used functions)
public class function
{
static Label statusLabel = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
static public void alert(string str)
{
statusLabel.Text = str;
}
static public void wait(int sec)
{
int i = 0;
while (i++ < sec)
{
statusLabel.Text = "Wait: " + (sec+1-i).ToString();
Thread.Sleep(1000);
}
}
}
script1.cs (script1,script2 ... it is about 30 mini programs)
public class script1
{
static public void Run()
{
function.alert("Script1 is running");
function.wait(5);
function.alert("Script1 is done");
}
}
Not the best solution
remove in function.cs
static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;
Form1.cs
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
script1.Run(this.statusLabel);
}
}
function.cs
public class function
{
private Label _statusLabel;
public scriptClass(Label statusLabel)
{
_statusLabel = statusLabel;
}
}
script1.cs (script1,script2 ... it is about 30 mini programs)
public class script1
{
static public void Run(Label statusLabel)
{
function _function = new function(statusLabel);
}
}
The statusLabel object is owned by, and should be encapsulated and hidden by, the Form1 class. To ensure good decoupling of your classes, as well as proper data hiding, only the Form1 class should be directly accessing it. And it should (by default) be able to access it via a field named statusLabel (i.e. no need to call this.Controls.Find() (nor should that even work from the function class, since that class also is not the owner of the object, nor of a Controls property).
The correct way to do this is for the script1 class to expose a StatusText property, and an event that is raised when the property value changes. There are two canonical ways to implement the event:
Implement an event named StatusTextChanged
Implement the INotifyPropertyChanged interface
Note that in your example, #2 is not an option because you are using static classes to implement your scripts. IMHO this is inadvisable for a variety of reasons, but since #1 is a perfectly fine solution I won't belabor that point. :)
The first looks like this:
class script1
{
public static string StatusText { get; private set; }
public static event EventHandler StatusTextChanged;
static public void Run()
{
ChangeStatusText("Script1 is running");
function.wait(5);
ChangeStatusText("Script1 is done");
}
static void ChangeStatusText(string text)
{
StatusText = text;
EventHandler handler = StatusTextChanged;
if (handler != null)
{
handler(null, EventArgs.Empty);
}
}
}
Then in Form1:
public partial class Form1
{
private void Form1_Load(object sender, EventArgs e)
{
script1.StatusTextChanged += (sender1, e1) => statusLabel.Text = script1.Text;
script1.Run();
...
script30.StatusTextChanged += (sender1, e1) => statusLabel.Text = script30.Text;
script30.Run();
}
}
Note in the above, each scriptX class has to reimplement the event. You could instead make a base class that each of the scriptX classes inherits, and which contains the event in question. Then the Form1 class need only subscribe to the one base class event. It would also address, or at least minimize the hassle of, the issue of leaving event handlers subscribed to 30 different events.
Of course, in this case then the Form1 class won't know which script is updating the text, but maybe that doesn't matter in your case.
Also note that if you did make the scriptX classes non-static, you might then again run into the issue of having to subscribe multiple times. But that is much more easily handled, since it seems certain in that case you'd use a base class, and so it would be easy to generalize the "subscribe, run script, unsubscribe" logic into a helper method.

Why is subscribed event always null?

I declare a subscription to event in:
public class MainClass
{
public void btndel_bar_Click(object sender, RoutedEventArgs e)
{
SomeClass sc = new SomeClass();
sc.FieldUpdate += new SomeClass.FieldUpdateHandler(sc_FieldUpdate);
}
void sc_FieldUpdate(object sender, ValueEventArgs e)
{
MessageBox.Show(e.Smth_property);
}
}
And here is I want to listen event:
public class Someclass
{
public delegate void FieldUpdateHandler(object sender, ValueEventArgs e);
public event FieldUpdateHandler FieldUpdate;
void Somemethod()
{
string str = "Steel";
ValueEventArgs args = new ValueEventArgs(str);
FieldUpdate(this, args);
}
}
A class which carries data:
public class ValueEventArgs : EventArgs
{
private string smth;
public ValueEventArgs(string smth)
{
this.smth = smth;
}
public string Smth_property
{
get { return smth; }
}
}
I always have FieldUpdate=null. How to solve it?
You're calling Somemethod() in the constructor, before the calling code gets a chance to add the event handler.
Therefore, the event is still null.
The moment you create the object of SomeClass your event would get reinitialized.
Make your event a static so that multiple objects of SomeClass would share it
public static event FieldUpdateHandler FieldUpdate;
I've read articles about delegates and events and after reading I always I thought to make all operations again. I did all over again and it works! Consequently I done something wrong when I did at the beginning of.

implementing delegates in c#

This would be the first time I'd use delegates in c# so please bear with me. I've read a lot about them but never thought of how/why to use this construct until now.
I have some code that looks like this:
public class DoWork()
{
public MethodWorkA(List<long> TheList) {}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
I call MethodWorkA from a method outside the class and MethodWorkA calls MethodWork 1 and 2. When I call methodA, I'd like to pass some sort of parameter so that sometimes it just does MethodWork1 and sometimes it does both MethodWork1 and MethodWork2.
So when I call the call it looks like this:
DoWork MyClass = new DoWork();
MyClass.MethodA...
Where does the delegate syntax fit in this?
Thanks.
public void MethodWorkA(Action<ParamType1, ParamType2> method) {
method(...);
}
You can call it using method group conversion:
MethodWorkA(someInstance.Method1);
You can also create a multicast delegate that calls two methods:
MethodWorkA(someInstance.Method1 + someInstance.Method2);
For what you described, you don't need delegates.
Just do something like this:
public class DoWork
{
public void MethodWorkA(List<long> theList, bool both)
{
if (both)
{
MethodWork1(1);
MethodWork2(1);
}
else MethodWork1(1);
}
public void MethodWork1(int parameters) { }
public void MethodWork2(int parameters) { }
}
If you're just experimenting with delegates, here goes:
public partial class Form1 : Form
{
Func<string, string> doThis;
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
doThis = do1;
Text = doThis("a");
doThis = do2;
Text = doThis("a");
}
string do1(string s)
{
MessageBox.Show(s);
return "1";
}
string do2(string s)
{
MessageBox.Show(s);
return "2";
}
}
Considering that all methods are inside the same class, and you call MethodWorkA function using an instance of the class, I honestly, don't see any reason in using Action<T> or delegate, as is I understood your question.
When I call methodA, I'd like to pass some sort of parameter so that
sometimes it just does MethodWork1 and sometimes it does both
MethodWork1 and MethodWork2.
Why do not just pass a simple parameter to MethodWorkA, like
public class DoWork()
{
public enum ExecutionSequence {CallMethod1, CallMethod2, CallBoth};
public MethodWorkA(List<long> TheList, ExecutionSequence exec)
{
if(exec == ExecutionSequence.CallMethod1)
MethodWork1(..);
else if(exec == ExecutionSequence.CallMethod2)
MethodWork2(..);
else if(exec == ExecutionSequence.Both)
{
MethodWork1(..);
MethodWork2(..);
}
}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
Much simplier and understandable for your class consumer.
If this is not what you want, please explain.
EDIT
Just to give you an idea what you can do:
Example:
public class Executor {
public void MainMethod(long parameter, IEnumerable<Action> functionsToCall) {
foreach(Action action in functionsToCall) {
action();
}
}
}
and in the code
void Main()
{
Executor exec = new Executor();
exec.MainMethod(10, new List<Action>{()=>{Console.WriteLine("Method1");},
()=>{Console.WriteLine("Method2");}
});
}
The output will be
Method1
Method2
In this way you, for example, can push into the collection only functions you want to execute. Sure, in this case, the decision logic (which functions have to be executed) is determined outside of the call.

Should I go with reflection or delegates (C#)?

In one of my previous questions I explained about a form class that contain form field objects to save data in a user profile object (using profile provider).
The code is here bellow. Basically what I would like to accomplish is to pass as a parameter to my form field objects the field of the Profile object that they should interact in order to save the data later on.
You can see that in the following line:
//LastNameFormLine is an control that was added to my form page.
//The ProfileField parameter stores the field of the UserProfile object that is being manipulated by this control
LastNameFormLine.ProfileField = "UserProfile.LastName";
I was reading about reflection to be able to save this value in the UserProfileVisitor class, but I came across this concept of delegate in C# which I am not sure yet if I fully grasp.
Is it possible to delegate the ProfileField to a property on my UserProfile class? Or should I forget about it and go with reflection?
What would you suggest?
public partial class UserProfileForm : CustomIntranetWebappUserControl
{
protected override void OnInit(EventArgs e)
{
//AutoEventWireup is set to false
Load += Page_Load;
CancelLinkButton.Click += CancelButtonClickEvent;
SaveLinkButton.Click += SaveButtonClickEvent;
base.OnInit(e);
}
private void SaveButtonClickEvent(object sender, EventArgs e)
{
VisitFormFields();
}
private void VisitFormFields()
{
var userProfileVisitor = new UserProfileVisitor();
foreach (var control in Controls)
{
if (control is FormFieldUserControl)
{
var formField = (FormFieldUserControl) control;
formField.Visit(userProfileVisitor);
}
}
userProfileVisitor.Save();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindText();
}
}
private void BindText()
{
LastNameFormLine.LabelText = string.Format("{0}:", HomePage.Localize("Last Name"));
LastNameFormLine.InputValue = UserProfile.LastName;
LastNameFormLine.IsMandatoryField = true;
LastNameFormLine.IsMultilineField = false;
LastNameFormLine.ProfileField = "UserProfile.LastName";
//... the rest of this method is exactly like the 4 lines above.
}
}
public abstract class FormFieldUserControl : CustomIntranetWebappUserControl
{
public string ProfileField { get; set; }
public abstract void Visit(UserProfileVisitor userProfileVisitor);
}
public partial class FormLineTextBox : FormFieldUserControl
{
//... irrelevant code removed...
public override void Visit(UserProfileVisitor userProfileVisitor)
{
if (userProfileVisitor == null)
{
Log.Error("UserProfileVisitor not defined for the field: " + ProfileField);
return;
}
userProfileVisitor.Visit(this);
}
}
public class UserProfileVisitor
{
public void Visit(FormLineTextBox formLine)
{
// The value of formLine.ProfileField is null!!!
Log.Debug(string.Format("Saving form field type {1} with profile field [{0}] and value {2}", formLine.ProfileField, formLine.GetType().Name, formLine.InputValue));
}
// ... removing irrelevant code...
public void Save()
{
Log.Debug("Triggering the save operation...");
}
}
Delegates are not for properties. However, Reflection is slow, may have issues with code security and it's not typesafe and may lead to runtime instead of compile-time problems on naming errors due to the late-bound nature.
That said, you may want to use getter and/or setter methods and use delegates on those.

Categories

Resources