2014-03-13 62 views
2

C#有一點新鮮感,並且接近我之外的某些東西。道歉的長度。如何與其他班級的表單控件進行通信?

我在Visual Studio C#Express中有一個Windows窗體應用程序,使用默認類VS spawns。我想從除聲明它的默認Form1以外的類開始並停止一個Marquee樣式progressBar。 這些似乎令人驚訝的困難,我相信我錯過了一些重要的東西。

我的項目具有Visual Studio自動生成的常用類: Form1.cs,Form1.Designer.cs,Program.cs。 我加了myClass.cs想說說加載條。 我將progressBar1欄添加到我的表單中,使用設計器設置Style:Marquee。

Form1.cs中「表()構造函數,我寫

this.progressBar1.Visible = false; 

這工作。 Intellisense'看到'progresBar1。 代碼Form1.cs中可以查看和控制progressBar1Form1.Designer.cs聲明。 這對我有意義。

但是,需要啓動和停止加載欄的功能必須存在於myClass.cs。 我希望能夠像這樣的代碼,內myClass.cs

public void myFunction(){ 
    Form1.progressBar1.visible=true 
    //do stuff that takes a bit of time 
    Form1.progressBar1.visible=false 
} 

這是行不通的。在myClass.cs中鍵入代碼時,智能感知無法'看到'progresBar1 事實上,智能感知不能「看」從myClass.cs內Form1.cs中什麼。 沒有公共propeties或功能添加到Form1永遠變得可見intellisense。 這對我來說沒有意義,我很困惑。 這似乎是你想要經常和輕鬆地做的事情。

一些搜索表明,這種對Form控件的外部訪問阻塞是有意設計的。有些東西與你的邏輯代碼與GUI代碼「解耦」,這在理論上是有意義的。所以顯然有一個預期的方法,但很難找到一個明確的例子。我只能找到完全在聲明它們的表單中控制的loadbars的示例,或者簡單地說明有關創建和註冊事件或使用Invoke或我知之甚少的其他事情的一半示例。有許多明顯的解決方案,但是我看不到的東西顯然適用於我,或者我能夠以我的無知來實施。

我想我可以做到這一點,如果我的表單是一個實例。 [編輯]不。實例與否,Form1控件永遠不會暴露在Form1的之外。CS

那麼,如何啓動和停止從不是缺省Form1中在聲明它之外的類跑馬燈式的進度,以正確的方法是什麼? 有沒有一個清晰有用的例子?

+0

你在哪裏創建myClass的實例? Form1的內部代碼? – Steve

+0

myClass是一個單獨的類,不在Form1中。這是一個大班,需要時間做許多事情。我在解決方案資源管理器中使用「添加類」來添加它。它與Program.cs和所有其他類共享其名稱空間。 –

+0

檢查此答案的鏈接[如何訪問另一個窗體中的控件](https://stackoverflow.com/a/38898134/7675357)。 –

回答

1

您無法訪問您的性質是這樣的:

Form1.progressBar1 

因爲Form1中是一類(而不是實例化對象)。您可以使用此方法訪問的唯一方法或屬性必須標記爲static

要回答你如何溝通的問題,你可能想使用你提到的事件的方法。首先,你需要一個事件在你的邏輯類:

public event Action<int> UpdateProgress; 

被稱爲就像一個功能:

if (UpdateProgress != null) 
    UpdateProgress(10); 

這聲明使用Action泛型委託一個新的事件,這意味着該監聽功能有返回void並將一個int作爲參數。

然後在你的表格代碼,你必須:

MyClass logic = new MyClass(); 
private void SomeFunction 
{  
    logic.UpdateProgress += UpdateProgressBar; 
} 

private void UpdateProgressBar(int newProgress) 
{ 
    progressBar1.BeginInvoke(new Action(() => 
    { 
     progressBar1.Value = newProgress; 
    })); 
} 

這將創建你的邏輯類的一個新實例,並分配功能「UpdateProgressBar」只要你的邏輯類引發的事件UpdateProgressBar被稱爲。該函數本身使用Dispatcher.BeginInvoke,因爲您的邏輯類可能不在UI線程上運行,並且您只能從該線程執行UI任務。

有是怎麼回事了很多在這裏,所以請讓我知道如果我能爲你澄清什麼!

+0

我會開始解釋這個概念從UpdateProgressBar方法開始,然後回去解釋你如何通過委託myClass的與myClass的方法中調用結束,但我認爲你是正確的。 – Steve

+0

有很多事情正在進行,但似乎是運作中的重要OOP原則。我會看到如果我可以讓它工作,然後提出問題。 –

+0

'調度員'。在當前情況下不存在。我應該使用什麼名字空間:'? –

0

我會創建一個具有性能符合形式的模型,並通過周圍。

所以,你會做這樣一個新的類...

using Windows.Forms; 

public class Form1Model { 
    public ProgressBar progressBar { get; set; } 
} 

然後,當你想你的其他類持有該功能,您將創建Form1Model的一個實例,填充它,並打電話給你功能

var fm = new Form1Model { 
    progressBar = this.progressBar1; 
}; 
otherClass.MyFunction(fm); 

現在你必須改變你的函數接受新的模式

public void MyFunction(Form1Model fm){ 
    // do stuff 
} 

另一種選擇是隻是把功能採取的形式的一個實例,而不是創建一個模型,但隨後你將要路過很多額外的比特你可能不會在意

public void MyFunction(Form1 form){ 
    // do stuff 
} 

然後你的表格上,你會調用此類

otherClass.myFunction(this); 

的功能,我建議第一種方式在第二,你可以控制數據被傳遞什麼周圍

+0

絕對是第一個在第二個,你不想要除非必須傳遞整個表單對象。我使用這種方法的唯一問題是它將「邏輯」類與UI類型緊密耦合。 – BradleyDotNET

+0

我可能已經進入界面和那些東西,但他說他是C#的新手,所以我儘量保持簡單 – mmeasor

0

您試圖訪問的類型Form1,而不是形式即時CE。我會告訴你,你如何訪問下面的實例。

我認爲Form1是保持只要打開應用程序運行的應用程序的主要形式。當您在Program.cs創建WinForms應用程序創建VS這段代碼:

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 
} 

一個簡單的方法,使您的主要形式訪問整個應用程序,使其通過一個公共靜態屬性訪問。改變這樣的

static class Program 
{ 
    public static Form1 MainForm { get; private set; } 

    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     MainForm = new Form1(); 
     Application.Run(MainForm); 
    } 
} 

代碼在Form1創建一個公開進度條的可見性屬性:

public bool IsProgressBarVisible 
{ 
    get { return this.progressBar1.Visible; } 
    set { this.progressBar1.Visible = value; } 

}

現在您可以在進度條可見從程序的任何部分像這樣:

Program.MainForm.IsProgressBarVisible = true; 

訪問的主要形式的另一種方法是,因爲它總是與第一形式中打開:

((Form1)Application.OpenForms(0)).IsProgressBarVisible = true; 

然而,它需要被澆鑄到正確類型的形式,因爲OpenForms返回Form


別忘了:Form只是一個像其他類一樣的類。你幾乎可以做任何你可以用其他課程做的所有事情。因此,只要不使用多線程,與窗體進行通信與其他對象的溝通並無太大區別。

相關問題