簡體   English   中英

如何使用Invoke,但使用C#中的object參數來訪問表單屬性?

[英]How do I access form properties with Invoke, but with object parameter in C#?

對不起,我無法最好地描述我的問題的標題。 目前,我使用Invoke來訪問表單上的屬性,效果很好,但是我對每個屬性都有一個功能,這非常不舒服。

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

每個功能看起來像這樣

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

我的問題是,我不能那樣做嗎

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

絕對不是那樣,我想不出更多的面向對象,但是我不是用相同的代碼編寫大量函數,而是通過傳遞我想更改的對象來使用一個嗎?

您可以創建一個使用委托參數來描述要執行的操作的方法。 然后,您可以擺脫重復的代碼。

這是一個示例:我在窗體上創建一個名為PerformAction的公共方法。 它以Action <MainForm>委托作為參數; 這位代表描述了應該采取的行動。

應該盡可能使用實例方法,但是為了完整起見,我創建了一個靜態版本,該靜態版本從Form.ActiveForm獲取Form實例。

代碼如下:

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

然后可以在另一個線程中這樣使用:

    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也可以設為通用,因此您可以在任何表單上使用它。 那么簽名將是:

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

如果您有一個在表單之間共享的通用基類,則可以這樣聲明它。 或者,您可以創建一個包含該方法的幫助程序類。

我問了一個類似的問題,但是對於WPF,原理卻是相同的。 修改喬恩·斯凱特(Jon skeet)為您提供的問題的答案,您可以使用類似以下的方法:

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

編輯:從使用form.Dispatcher更改。

您可以將重用的功能移動到兩個單獨的靜態方法(一個擴展)中,這將大大簡化您在靜態助手和屬性中的使用。

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

對於您的財產:

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

對於您的靜態助手:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM