Passing an Action with Different Parameters - c#

I have a class in C# named Button and I want the Button have a functionality that can be passed through its constructor and whenever the Button was pressed the Action executes.
Button(Rect rect, string text, Action Func);
I have used Action and It worked perfectly until I found out that I can't pass a void Action with arguments.
For example:
void DoSomething(string str);
How can I be able to pass any void Action with any arguments?

The button doesn't have to care about the argument, but it still needs to be passed a delegate with no arguments and returning void. This is easily done:
new Button(rect, text, () => YourMethod(whateverArgument))
Depending on what you're trying to do, whateverArgument can be a local, a constant or a field. Just think about when it's supposed to read the value to pass to the inner method.

Sure you can pass arguments, just use the following:
Button b = new Button(.., .., () => DoSomething("YourString");

I advice you to use simplefied command pattern:
Create base class or interface Command
interface ICommand
{
void Execute();
}
//Create secific command and pass parameters in constructor:
class Command : ICommand
{
public Command(string str)
{
//do smth
}
void Execute()
{
//do smth
}
}
Button(Rect rect, string text, ICommand cmd)
{
cmd.Execute();
}

Related

How to use events in c#?

I am completely new to events in c# and this is what I want to do:
I have two methods:
OpenPage1();
OpenPage2();
When either of these methods is called, I want a third method named as PerformSomeTask() to be called.
I believe that this can be done by event handling. Could anyone tell me how to do this?
All you have to do in your class is to add an event with a correct eventHandler (Action in your example). The eventHandler should correspond the method that will subscribe to this event.
Then you fire the event from the openPage Methods.
You must check for null in case no one subscribed to this event.
public class Foo
{
public event Action theEvent;
public void OpenPage1()
{
if (theEvent != null)
theEvent();
}
public void OpenPage2()
{
if (theEvent != null)
theEvent();
}
}
public class Bar
{
public int Counter { get; set; }
public void PerformSomeTask()
{
Counter++;
}
}
And here's a test that you can run to see it all together:
[TestMethod]
public void TestMethod1()
{
var foo = new Foo();
var bar = new Bar();
foo.theEvent += bar.PerformSomeTask;
foo.OpenPage1();
foo.OpenPage2();
Assert.AreEqual(2, bar.Counter);
}
Events is a big part of C#.
To be simple, you need first a delegate that describe type of called method. In your example, PerformSomeTask is void and take no parameters.
So declare in your class
public delegate void PerformSomeTask();
Then, you need to declare event, which is the member that will called to launch your function
public event PerformSomeTask OnPerformSomeTask;
On your both methods, OpenPage1 and OpenPage2, you need to check if someone subscribe to your event, if yes, call it.
if(OnPerformSomeTask != null)
OnPerformSomeTask();
This will launch every method that subscribe to your event. Subscribers can be multiple.
To subscribe, just do it like this :
YourClass.OnPerformSomeTask += MyVoidMethod;
[...]
public void MyVoidMethod() { DoSomething(); [...] }
Your void method will be called everytime your run OpenPage1 and OpenPage2
If you need some parameters, juste change your delegate to proceed.
public delegate void PerformSomeTask(string myParam);
Then, your methods will have this parameter as standard function parameter (call your event with your value to pass it as parameter to every subscriber function).

How to use CanClose()?

I'm trying to close my Caliburn window but unsure how to use it.
CanClose expects one item in it's parameter
Parameter 1 - Action callback
I'm simply trying to use the function this.CanClose() but unsure what goes inbetween the parenthesis
public void closeWindow()
{
this.CanClose();
}
public override void CanClose(Action<bool> callback)
{
base.CanClose(callback);
}
You can use the callback like this:
CanClose( p => { DoSomething(); } );
You should insert callback method as parameter.
this.CanClose(MyMethod);

c#, .net, delegate, asynchronous callback. What am I doing wrong here?

Heres a little class for a button in a menu in a game.
I'd like to be able to pass a delegate method _triggerMethod when I'm instantiating each button. Then that delegate method will get called when that button instances trigger method is called.
I'm trying out delegates in C# for the first time here. And as far as I'm interpreting the documentation here what I'm doing should work but visual studio is giving me a compile error in the Trigger method.
According to msdn article the code calling the delegate doesnt need to know about the original methods paramaters and such. What am I doing wrong?
Also in the msdn article they are only typing "Del" and that does not work for me. I must type "Delegate" which is odd.
class MenuItem
{
private Rectangle clickArea;
private string displayText;
private Vector2 _position;
private Delegate _triggerMethod;
public MenuItem(Vector2 pos,string txt,Delegate trig)
{
displayText = txt;
_position = pos;
_triggerMethod = trig;
}
public void Draw(SpriteBatch sb)
{
}
public void Select()
{
}
public void DeSelect()
{
}
public void IsMouseOnMe()
{
}
public void Trigger()
{
_triggerMethod();
}
}
You haven't created any delegate definition.
Example (from the MSDN-page you linked):
public delegate void Del(string message);
Then, you need to use that as your Type:
** snip **
private Del _triggerMethod;
public MenuItem(Vector2 pos,string txt,Del trig)
{
displayText = txt;
_position = pos;
_triggerMethod = trig;
}
** snip **
public void Trigger()
{
_triggerMethod("some message");
}
You can pass references of the delegate around without actually knowing what arguments it expects (since it's just a normal reference), but when you want to invoke it, you do need to give it the correct parameters.
You need to define the Del type if you want to use it:
public delegate void Del(string message);
public class MenuItem
{
private Del _triggerMethod;
public void Trigger()
{
_triggerMethod("Message");
}
}
Note that you can use the built-in Action<string> delegate type instead of defining your own:
Action<string> _triggerMethod;
_triggerMethod("Message");
If you just use the Delegate type, you can invoke it using DynamicInvoke:
public void Trigger()
{
_triggerMethod.DynamicInvoke();
}

Using methods as a default parameter

I'm looking to create a Button class in my custom XNA GUI that accepts methods as an argument, similar to how, in Python's tkinter you can just set the function to be called with Button.config(command = a_method) .
I've read about using delegates as parameters here, here and here, but I don't seem to be any closer to getting it working. I don't fully understand how delegates work, but I've tried several different things unsuccessfully, like using Func<int>? command = null in order to test later to see if command is null then I'd call the preset default, but then I get a Func cannot be nullable type or something similar.
Ideally the code'd be something like:
class Button
{
//Don't know what to put instead of Func
Func command;
// accepts an argument that will be stored for an OnClick event
public Button(Action command = DefaultMethod)
{
if (command != DefaultMethod)
{
this.command = command;
}
}
}
But it seems like everything I've tried is not working out.
Default parameters must be a compile time constant. In C#, Delegates can't be constants. You can achieve a similar result by providing your own default in the implementation. (just using Winforms here)
private void button1_Click(object sender, EventArgs e)
{
Button(new Action(Print));
Button();
}
public void Button(Action command = null)
{
if (command == null)
{
command = DefaultMethod;
}
command.Invoke();
}
private void DefaultMethod()
{
MessageBox.Show("default");
}
private void Print()
{
MessageBox.Show("printed");
}
The error you got about Func<T> not being nullable it right - it is a reference type and only value types can be nullable.
To default a Func<T> parameter to null, you can simply write:
Func<int> command = null
If you are interested in a default value, would something like this work?
class Button
{
//Don't know what to put instead of Func
private readonly Func defaultMethod = ""?
Func command;
// accepts an argument that will be stored for an OnClick event
public Button(Action command)
{
if (command != defaultMethod)
{
this.command = command;
}
}
}

C# How can I Learn Class that Call My Method in another Class

public class Form1:Form
{
public Form1()
{
}
Form1_Load(object Sender,EventArgs e)
{
SampleClass Sample=new SampleClass();
Sample.MyMethod();
}
}
this is first class in my project and second is
Hi All
public class SampleClass
{
public void MyMethod()
{
//When Form1 or another class call this Method
//I want to know it for example
Caller.Title="Deneme";
//
//Unless send parametr.How Can I learn Caller class and i change it items?
}
}
The caller will have to pass a reference to itself into the method.
public void MyMethod(Form caller)
{
caller.Title="Deneme";
}
Or if you don't want the SampleClass to have a strong link to the Form class - it may be in a separate assembly that doesnt reference Windows form, you could pass in an Action that gets called with the correct string passed in.
Form1_Load(object Sender,EventArgs e)
{
SampleClass Sample=new SampleClass();
Sample.MyMethod( title => this.Title = title );
}
and
public void MyMethod(Action<string> setTitle )
{
setTitle ("Deneme");
}
Edit to explain delegates
The Action parameter
The Action parameter on MyMethod is essentially a variable that contains code that can be run. (It does take a little head twisting to fully understand the concept.) The <string> part of the type says that we can pass in a string to this code that is going to be run.
Then the line that goes
setTitle ("Deneme");
is calling this code and passing it the text "Deneme". This is the text that you want to set the Windows title to be. Now, the MyMethod method actually doesnt know that it is going to be setting the Windows title to be this text. This has become the responsibility of the caller. (If you want MyMethod to be absolutely certain that it is setting the Title of a Form, then the first solution is the one that you want.)
Calling
The caller of the method calls
MyMethod( title => this.Title = title );
The parameter to MyMethod is :
title => this.Title = title
This is the code that you are passing to the Action variable. The title to the left of the => is the variable that will have the String that is passed to it when the code is invoked, and the stuff to the right of the => is the code that gets called.
So when the form calls MyMethod, it is saying I want that string and I'm going to set my title to it.
The beauty of this is that MyMethod doesn't know about the form. If you want to reuse your class when you write a Console application, you may call :
MyMethod ( title => Console.WriteLine (title) );
MyMethod doesn't need to be touched at all!
You could try:
public class SampleClass
{
public void MyMethod(Form sender)
{
sender.Text = "title";
}
}

Categories

Resources