Comment puis-je accéder aux propriétés de forme avec Invoke, mais avec le paramètre d'objet en C #?

StackOverflow https://stackoverflow.com/questions/740337

  •  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?

Était-ce utile?

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 comme argument; ce délégué décrit l'action qui doit être prise.

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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top