Como faço para propriedades do formulário de acesso com Invoke, mas com o parâmetro objeto em C #?
-
09-09-2019 - |
Pergunta
Eu não poderia descrever o título da minha pergunta o melhor, me desculpe. Atualmente, eu uso Invoke para acessar as propriedades no meu formulário, ele funciona perfeito, mas eu tenho uma função para cada propriedade, que é bastante não confortável.
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;
}
Cada uma destas funções parece com o
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;
}
}
}
A minha pergunta é, eu não posso fazê-lo assim
public static void EnableObject(object name)
{
var form = Form.ActiveForm as FormMain;
if (form != null)
form.Enable + name = enabled;
}
Não é definitivamente dessa forma, eu não conseguia pensar em algo mais OO, mas em vez de escrever toneladas de funções com o mesmo código, não consigo usar uma passando o objeto que eu gostaria de mudar?
Solução
Você pode criar um método que leva um delegado parâmetro que descreve a ação a ser executada. Então você pode se livrar do código repetido.
Aqui está um exemplo: eu crio um método público chamado PerformAction no meu formulário. É preciso um Action
O método de instância deve ser usada quando possível, mas para ser completo eu criei uma versão estática que recebe a instância do formulário a partir Form.ActiveForm.
Os olhares código como este:
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);
}
}
}
E pode então ser usado como este de outro segmento:
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 poderia também ser feita genérico para que você possa usá-lo em qualquer de suas formas. Em seguida, a assinatura seria:
public void PerformAction<T>(Action<T> action)
where T : Form
{
...
}
Não faria sentido declará-la como esta se você tem uma classe base comum que é compartilhado entre seus formulários. Alternativamente, você pode criar uma classe auxiliar que contém o método.
Outras dicas
Eu fiz uma pergunta semelhante , mas para WPF, o princípio é o mesmo embora. Modificando a resposta que foi dada a mim por Jon Skeet para sua pergunta você poderia usar algo como isto:
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) });
}
Edit:. Mudou de usar form.Dispatcher
Você pode mover a funcionalidade reutilizado em dois métodos estáticos Sperate (um ramal), que irá simplificar muito o que você tem nas ajudantes estáticos e propriedades.
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);
}
}
E para as suas propriedades:
public int EnableLogin
{
set { this.InvokeEx(f => f.btnLogin.Enabled = value == 0); }
}
E para seus ajudantes estáticos:
public static void EnableLogin(int enabled)
{
FormHelpers.InvokeOnActive<FormMain>(f => f.EnableLogin = enabled);
}