How to use CanClose()? - c#

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);

Related

Godot C# "Error calling method from signal"

Given my scene tree:
Main_control (Type:Control) (Parent)
mnk_game (Type: Control) (Child)
I can run methods in mnk_game's script using signals from Main_control, but it won’t work the other way around (calling a method in Main_control using a signal from mnk_game)
Error:
emit_signal: Error calling method from signal 'mnk_game_finished': 'Control(Main_control.cs)::mnk_show_game': Method not found..
Parent's code:
public class Main_control : Control
{
public override void _Ready()
{pass}
public void mnk_show_game()
{
GD.Print("mnk_show_game reached"); //What I want to reach
}
}
Child code:
public class mnk_game : Control
{
[Signal]
public delegate void mnk_game_finished();
private Godot.Control game_controller;
public override void _Ready()
{
game_controller = (Control)GetParent<Godot.Control>();
this.Connect("mnk_game_finished", game_controller, "mnk_show_game");
}
public void any_method()
{
this.EmitSignal("mnk_game_finished");
}
}
When I call the any_method method at the child's script, I want to be able to reach mnk_show_game method in the parent's script. Can I do this? If so, how?
I don't have much experience using Godot with C#, but I can see that mnk_game_finished was defined without parameters and mnk_show_game also does not take parameters. However, you are emitting the signal with a parameter this.EmitSignal("mnk_game_finished", ds.board). Try to emit the signal without a parameter like so: this.EmitSignal("mnk_game_finished") or define your delegate and function with parameters.

Passing an Action with Different Parameters

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();
}

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();
}

C# Control.Invoke a method group

I am using threads to run long operations in my program's UI so that it doesn't lock up. However, in those tasks I need to update controls, which is impossible not from the thread they were created on. It is suggested to use control.BeginInvoke(Delegate) to execute the method you want.
However, to do that you have to declare a delegate type and only then you can call them.
So, it goes like this: if I want to execute method void Update(), i have to go:
delegate void CallbackVoid();
void Update() {...}
...(in task code)...
this.BeginInvoke(new CallbackVoid(Update));
This is rather tiresome to do for every single method out there. Can't I just somehow do it naturally, like:
void Update() {...}
this.BeginInvoke(Update);
One option which simplified things is to add an extension method:
public static void BeginInvokeAction(this Control control, Action action)
{
control.BeginInvoke(action);
}
Then you can just use:
this.BeginInvokeAction(action);
The reason this works is that we're now providing a concrete delegate type for the compiler to convert the method group to.
UPDATED: WORKS FOR WPF!!!
You can use short syntax with anonymous methods, without even declaring your methods
Dispatcher.BeginInvoke(DispatcherPriority.Background, new MethodInvoker(() =>
{
//Your Update code
}));
Try the following:
if (this.controlname.InvokeRequired && !this.controlname.IsDisposed)
{
Invoke(new MethodInvoker(delegate()
{
//Update control on GUI here!
}));
else if(!this.controlname.IsDisposed)
{
//AND here!
}
BeginInvoke is asynchronous, Invoke is synchronous, which one you use depends on what you're trying to do. If you need the call to complete before you move on, then you want synchronous calls.
Here's my favorite construct for synchronous invokes:
static void InvokeIfRequired(Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action.Invoke();
}
}
Used:
void MyTestFunction()
{
InvokeIfRequired(myControl, () =>
{
MyFunction();
MyOtherFunction();
});
// Or more simply:
InvokeIfRequired(myControl, () => MyFunction());
}
There is a little overhead in the creation of the Action, but it simplifies the code quite a bit to not have to think about the details everywhere.

What is considered good programming practice in multi-threaded winform applications with delegate usage?

I'm modifying an application written in C# that makes heavy-use of multi-threading to play audio files and display images to a user. Given that it is multi-threaded, I need to use the Invoke method often to change form elements. I'm running into a pattern that I'm not very comfortable with, where I find myself writing frequent, small, delegate methods that typically only do one thing. An example of this is as follows:
delegate void setImageCallback(Image img);
private void setImage(Image img)
{
this.pictureBox1.Image = img;
}
private void someOtherMethod()
{
...
if (this.pictureBox1.InvokeRequired)
{
this.Invoke(new setImageCallback(setImage), Image.FromFile("example.png");
}
else
{
this.pictureBox1.Image = Image.FromFile("example.png");
}
...
}
How do people generally handle these situations, so that you don't find yourself writing an absurd number of delegates and methods just to remain thread-safe? Obviously, consolidation of similar methods is great, but if I potentially need to update every form element on my form, I don't want to have a "modify" delegate and method for each of these.
Thanks.
A good example is here.
this.BeginInvoke( (Action) (()=>
{
pictureBox1.Image = Image.FromFile("example.png");
}));
You definitely don't need a separate delegate for each. You can use Action delegates and lambda expressions to simplify it, like this:
private void SomeOtherMethod()
{
Action action = () => pictureBox1.Image = Image.FromFile("example.png");
if (pictureBox1.InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
Or you can separate out the if statement and InvokeRequired check and generalize it even more, like this:
public static void InvokeIfRequired(Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
private void SomeOtherMethod()
{
InvokeIfRequired(() => pictureBox1.Image = Image.FromFile("example.png");
}
I would use the MethodInvoker type in conjunction with an anonymous method or lambda expression. I would also build the invocation logic into the method itself, rather than using a separate thread-safe method:
void SomeMethod(/* with whatever args */) {
if (InvokeRequired)
Invoke(new MethodInvoker(() => SomeMethod(/* args used to call method */)));
else
// the method body itself
}

Categories

Resources