Comment puis-je accéder aux propriétés de forme avec Invoke, mais avec le paramètre d'objet en C #?
-
09-09-2019 - |
Question
Je ne pouvais pas décrire le titre de ma question le meilleur, je suis désolé. À l'heure actuelle, j'utilise Invoke pour accéder aux propriétés de ma forme, il fonctionne parfaitement, mais j'ai une fonction pour chaque propriété, ce qui est tout à fait mal à l'aise.
public static void EnableLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableLogin = enabled;
}
public static void EnableConfirm(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableConfirm = enabled;
}
public static void EnableRetry(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableRetry = enabled;
}
public static void EnableTABLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.EnableTABLogin = enabled;
}
Chacune de ces fonctions ressemble que
public int EnableLogin
{
set
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
if (value == 0)
this.btnLogin.Enabled = false;
else
this.btnLogin.Enabled = true;
});
}
else
{
if (value == 0)
this.btnLogin.Enabled = false;
else
this.btnLogin.Enabled = true;
}
}
}
Ma question est, je ne peux pas le faire comme ça
public static void EnableObject(object name)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.Enable + name = enabled;
}
Il est certainement pas de cette façon, je ne pouvais pas penser à quelque chose de plus OO, mais au lieu d'écrire des tonnes de fonctions avec la même code, je ne peux pas utiliser un en passant l'objet que je voudrais changer?
La solution
Vous pouvez créer une méthode qui prend un paramètre délégué décrivant l'action à effectuer. Ensuite, vous pouvez vous débarrasser du code répété.
est un exemple: je crée une méthode publique appelée PerformAction sur ma forme. Il faut un délégué Action
La méthode d'instance doit être utilisé lorsque cela est possible, mais pour être complet, je créé une version statique qui obtient l'instance de formulaire de Form.ActiveForm.
Le code ressemble à ceci:
using System;
using System.Windows.Forms;
namespace WinFormTest
{
public partial class MainForm : Form
{
public void PerformAction(Action<MainForm> action)
{
if (InvokeRequired)
Invoke(action,this);
else
action(this);
}
public static void PerformActionOnMainForm(Action<MainForm> action)
{
var form = ActiveForm as MainForm;
if ( form!= null)
form.PerformAction(action);
}
}
}
Et peut ensuite être utilisé comme celui-ci d'un autre thread:
MainForm.PerformActionOnMainForm(form => form.Text = "My form");
// The action can also be a code block or a method:
MainForm.PerformActionOnMainForm(form =>
{
form.Width = 200;
form.Height = 300;
form.Left = 100;
form.Top = 200;
});
PerformAction pourrait également être réalisée générique afin que vous puissiez l'utiliser sur l'une de vos formes. Ensuite, la signature serait:
public void PerformAction<T>(Action<T> action)
where T : Form
{
...
}
Il serait logique de le déclarer comme si vous avez une classe de base commune qui est partagée entre vos formes. Sinon, vous pouvez créer une classe d'aide contenant la méthode.
Autres conseils
J'ai posé une question similaire mais pour WPF, le principe est le même que. La modification de la réponse qui a été fournie à moi par Jon Skeet pour votre question, vous pouvez utiliser quelque chose comme ceci:
public static void InvokeIfNecessary(Form form, MethodInvoker action)
{
if (form.InvokeRequired)
{
form.Invoke(DispatcherPriority.Normal, action);
}
else
{
action();
}
}
public static void EnableLogin(int enabled)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
InvokeIfNecessary(form, delegate { form.btnLogin.Enabled = (enabled != 0) });
}
Modifier. Changement de l'utilisation form.Dispatcher
Vous pouvez déplacer la fonctionnalité réutilisée en deux méthodes statiques sperate (une extension) qui simplifie grandement ce que vous avez dans les aides et les propriétés statiques.
public static class FormHelpers
{
public static void InvokeOnActive<TForm>(Action<TForm> action)
where TForm : Form
{
TForm activeForm = Form.ActiveForm as TForm;
if (activeForm != null)
activeForm.InvokeEx(f => { action(f); return f; });
}
}
public static class ControlExtensions
{
public static TResult InvokeEx<TControl, TResult>(this TControl control,
Func<TControl, TResult> func)
where TControl : Control
{
if (control.InvokeRequired)
return (TResult)control.Invoke(func, control);
else
return func(control);
}
}
Et pour vos propriétés:
public int EnableLogin
{
set { this.InvokeEx(f => f.btnLogin.Enabled = value == 0); }
}
Et pour vos aides statiques:
public static void EnableLogin(int enabled)
{
FormHelpers.InvokeOnActive<FormMain>(f => f.EnableLogin = enabled);
}