Domanda

Non potrei descrivere il titolo del mio dubbio la migliore, mi dispiace. Attualmente, io uso Invoke per accedere alle proprietà sulla mia forma, funziona perfettamente, ma ho una funzione per ogni proprietà, che è abbastanza non è comodo.

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

Ciascuna di queste funzioni sembra che

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

La mia domanda è, non posso fare in quel modo

    public static void EnableObject(object name)
    {
        var form = Form.ActiveForm as FormMain;
        if (form != null)
            form.Enable + name = enabled;
    }

E 'sicuramente non in questo modo, non riuscivo a pensare a qualcosa di più OO, ma invece di scrivere tonnellate di funzioni con lo stesso codice, non è possibile utilizzare uno passando l'oggetto mi piacerebbe cambiare?

È stato utile?

Soluzione

È possibile creare un metodo che accetta un parametro delegato che descrive l'azione da eseguire. Poi si potrebbe sbarazzarsi del codice ripetuto.

Ecco un esempio: creo un metodo pubblico chiamato PerformAction sulla mia forma. Ci vuole un'azione delegato come argomento; questo delegato descrive l'azione che dovrebbe essere preso.

Il metodo di istanza deve essere utilizzato quando possibile, ma per completezza ho creato una versione statica che ottiene l'istanza modulo dal Form.ActiveForm.

Il codice è simile al seguente:

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 può quindi essere utilizzato in questo modo da un altro 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 potrebbe anche essere fatto in modo generico si può utilizzare su una qualsiasi delle forme. Poi la firma potrebbe essere:

public void PerformAction<T>(Action<T> action) 
    where T : Form 
    { 
        ... 
    }

In questo senso sarebbe di dichiararla come questo se si dispone di una classe base comune che è condivisa tra i moduli. In alternativa, è possibile creare una classe di supporto che contiene il metodo.

Altri suggerimenti

Ho chiesto href="https://stackoverflow.com/questions/657037/why-the-overhead-for-multi-threaded-access-to-wpf-ui-controls"> domanda simile ma per WPF, il principio è lo stesso però. Modificare la risposta che è stata fornita a me da Jon Skeet per la tua domanda si potrebbe usare qualcosa di simile:

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

Modifica:. Cambiato da utilizzare form.Dispatcher

È possibile spostare la funzionalità riutilizzato in due metodi statici Sperate (un'estensione) che sarà notevolmente semplificare quello che hai nelle aiutanti e le proprietà statiche.

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 per le proprietà:

public int EnableLogin
{
  set { this.InvokeEx(f => f.btnLogin.Enabled = value == 0); }
}

E per i vostri aiutanti statico:

public static void EnableLogin(int enabled)
{
  FormHelpers.InvokeOnActive<FormMain>(f => f.EnableLogin = enabled);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top