2009-04-11 2 views
0

Ich konnte den Titel meiner Frage nicht am besten beschreiben, tut mir leid. Derzeit verwende ich Invoke, um auf die Eigenschaften in meinem Formular zuzugreifen. Es funktioniert perfekt, aber ich habe eine Funktion für jede Eigenschaft, die ziemlich unkomfortabel ist.Wie greife ich auf Formulareigenschaften mit Invoke, aber mit Objektparameter in C#?

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

sieht Jede dieser Funktionen wie die

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

Meine Frage ist, kann ich es nicht tun, wie die

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

Es ist definitiv nicht so, könnte ich nicht Denken Sie an etwas mehr OO, aber anstatt Tonnen von Funktionen mit demselben Code zu schreiben, kann ich nicht einen verwenden, indem ich das Objekt übergebe, das ich gerne ändern würde?

Antwort

2

Sie können eine Methode erstellen, die einen Delegate-Parameter verwendet, der die durchzuführende Aktion beschreibt. Dann könnten Sie den wiederholten Code loswerden.

Hier ist ein Beispiel: Ich erstelle eine öffentliche Methode namens PerformAction auf meinem Formular. Es dauert eine Aktion <MainForm> Delegat als Argument; Dieser Delegat beschreibt die Aktion, die ausgeführt werden sollte.

Die Instanzmethode sollte verwendet werden, wenn möglich, aber der Vollständigkeit halber habe ich eine statische Version erstellt, die die Formularinstanz aus Form.ActiveForm bezieht.

Der Code sieht wie folgt aus:

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

Und kann dann wie folgt aus einem anderen Thread verwendet werden:

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

Perform auch Generika hergestellt werden könnten, so dass Sie es auf einem beliebigen Ihrer verwenden Formen. Dann würde die Unterschrift sein:

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

Es wäre sinnvoll, es so zu erklären, wenn Sie eine gemeinsame Basisklasse haben, die unter Ihren Formen geteilt wird. Alternativ könnten Sie eine Hilfsklasse erstellen, die die Methode enthält.

+0

ich sehr interessiert bin, tun Sie dies bitte. –

+0

Sehr schön, aber es funktioniert nicht.Es gibt mir einen Fehler in dieser Zeile "Misc.PerformActionOnMainForm (FormMain => FormMain.groupMain.Enabled = true); "Fehler" FormMain.groupMain "ist aufgrund seiner Schutzstufe nicht erreichbar." Ich möchte die Änderung nicht in public ändern, aber ich habe es versucht - Ausnahme, nicht funktioniert –

+0

Eigentlich funktioniert es, wenn alles "geschützt intern" ist. Toll, danke! –

0

Ich fragte eine similar question aber für WPF, das Prinzip ist das gleiche obwohl. Ändern der Antwort, die von Jon Skeet für Ihre Frage an mich zur Verfügung gestellt wurde, um Ihnen so etwas wie diese verwenden:

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: Geändert verwenden form.Dispatcher.

+0

Dies beschreibt auch das Grundprinzip, der Code ist jedoch falsch. form.Dispatcher existiert nicht in WinForms. – driis

+0

Ja, auch Sie können nicht schreiben "Form .InvokeIfNecessary (form, delegate {form.btnLogin.Enabled = (aktiviert! = 0)}); "eckige Klammern {}" können nicht verwendet werden. Außerdem möchte ich etwas Ähnliches für die EnableLogin-Methode sehen. Warum nicht die EnableProperty-Methode mit Parameter: die Eigenschaft –

+0

Ok Ich habe das zB bearbeitet, um die Dispatcher-Referenz zu entfernen, da es sich um eine WPF-Sache handelt.In Bezug auf die Verwendung der EnableLogin-Eigenschaft schnitt ich den Setter aus wie im Beispiel a viel Code, um einen Bool einzustellen und kann in einer einzigen Zeile erfolgen. Wenn Sie mehr im Setter tun müssen, könnte es noch verwendet werden. – sipwiz

0

Sie können die wiederverwendbare Funktionalität in zwei separate statische Methoden (eine Erweiterung) verschieben, was das, was Sie in den statischen Helfern und Eigenschaften haben, erheblich vereinfacht.

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

Und für Ihre Eigenschaften:

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

Und für Ihre statischen Helfer:

public static void EnableLogin(int enabled) 
{ 
    FormHelpers.InvokeOnActive<FormMain>(f => f.EnableLogin = enabled); 
}