2014-02-18 61 views
1

我似乎對一個簡單的問題有很大的麻煩。是的,我是新來的C#,但我試圖瞭解我能做什麼,而不用跳過來發布問題。在這種情況下,我只是覺得我沒有問正確的問題。使用c通信或訪問另一個父母使用c#

無代碼樣本將幫助這裏,因爲我說的是基本(實現)。我還沒有真正編碼任何東西,只需使用視覺生成器來創建我的窗體和菜單。

我遇到的問題是,當我選擇一個菜單項(稱之爲:集路徑)我想我的主要形式,對列表視圖,從選擇時,我打Form2上確定的路徑加載。所以我做了一個簡單的查找文件夾對話框,並將我的新路徑存儲在form2文本框中。當我在該form2上點擊確定時,我想要我的listview form1填充。我知道如何做到這一切,但我不能在我的生活中從form2訪問form1,反之亦然。

我試圖使一個回調函數,但我得到的,因爲我的Form1上是靜態的非靜態變量不能被引用...錯誤,所以我不能創造任何非靜態方法。我查看了EventArgs,但這看起來像是對這樣一個常見請求的過度殺手。

那麼,什麼是做到這一點的一般方法是什麼?

+0

一般來說,您將使用ShowDialog()顯示Form2,然後在Form1中檢查DialogResult.OK的結果(點擊「OK」按鈕時在Form2中將DialogResult設置爲OK)。正如RobertHavey所解釋的那樣,您將使用Form2的引用來訪問所需的值。缺少的成分是,您不能(默認情況下)訪問存儲在Form2上的TextBox中的值。您可以通過將TextBox的Modifiers()屬性設置爲Public來「解決」此問題。然而,首選的方法是在Form2上創建一個自定義屬性來保存該值。 –

+0

完美! DialogResult正是我所需要的。我忘記了窗戶的回報。 –

回答

1

對於訪問另一個表單上的成員,Robert的回答是正確的。但是,一般來說,你應該保存你的應用程序的狀態(稱爲「模型」),從用戶界面的狀態分別(稱之爲「視圖」)。隨着您的應用程序增長超過一個或兩個交互,這變得非常重要。關於如何將兩者結合在一起(例如Google的「模型 - 視圖 - 控制器」(MVC)和「模型 - 視圖 - 視圖模型」(MVVM)),有幾種哲學或模式,如果你真的想要正確地做到這一點,會推薦學習這些。我的首選是MVVM方法,即使它是在設計時考慮WPF應用程序,也可以使用Windows Forms輕鬆完成。

在.NET中,代碼應該使用來實現您的視圖模型和視圖之間的連接基本片被稱爲INotifyPropertyChanged的接口。您創建一個實現了這個接口,併發送通知的類每當屬性發生變化,因此,例如你的路徑屬性,你將創建這個類:

class ViewModel : INotifyPropertyChanged 
{ 
    private string path; 
    public string Path 
    { 
     get { return path; } 
     set { 
      if (value != path) 
      { 
       path = value; 
       NotifyPropertyChanged(); 
      } 
     } 
    } 

    // This event gets triggered whenever a property changes. 
    public event PropertyChangedEventHandler PropertyChanged; 

    // This will cause the event to actually be triggered. It automatically determines the name of the property that triggered it using the [CallerMemberName] attribute - just a bit of .NET 4.5 sweetness. :) 
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

它可能看起來像很多工作,但現在在你的Form1中您可以創建一個新的「ViewModel」實例,訂閱該事件,然後將該實例傳遞給form2。然後,只要用戶選擇不同的路徑,form2就更新視圖模型實例上的Path屬性。

所以,Form1中需要靠近頂部驗證碼:

private ViewModel viewmodel = new ViewModel(); 

而這正好在Form1構造函數:

viewmodel.PropertyChanged += new EventHandler(OnPathChanged); 

而且當你創建/顯示窗口2:

var form2 = new Form2(viewmodel); // Note, the viewmodel instance is being passed to the form2 constructor 
form2.Show(); 

然後,form2構造函數將自己的引用存儲到「viewmodel」實例中,並且每當th e路徑被用戶改變。

private ViewModel viewmodel; 

public Form2(ViewModel viewmodel) 
{ 
    this.viewmodel = viewmodel; 
    ... // Other stuff to set up your controls etc. goes here 
} 

private void PathChanged(object sender, EventArgs e) // This may be named differently in your code; it's the event handler that gets called when the path changes 
{ 
    // This will automatically notify the event handler in Form1! It's super-elegant and flexible. 
    this.viewmodel.Path = txtPath.Text; // Assuming you have a textbox called txtPath 
} 

最後事件處理程序在Form1中:

private void OnPathChanged(object sender, EventArgs e) 
{ 
    var newPath = viewmodel.Path; // Get the updated path back from the viewmodel 
    //TODO: Whatever you want to do when the path changes. 
} 

下面是使用Windows窗體一個非常好的MVVM介紹的鏈接,它採用兩種形式就像你在你的例子都有。 MVVM (Model-View-ViewModel) Pattern For Windows Form Applications, using C#

+0

我認爲這回答了最好的問題,但DialogResult是我真正想要的(對於漫長的解釋,我是錯的)。 –

+0

沒問題。你的解釋很好! (儘管一些代碼片段可以很好地包含在類似的問題中,例如類名和在form1中創建/顯示form2的地方),我認爲看到不同的方法會很有幫助 - 您現在需要的直接解決方案,以及稍後在應用程序增長時需要的更精細的一個。 –

1

如果您需要爲另一種形式的訪問的東西,只是從你的第一種形式持有對它的引用,就像這樣:

form2 = new Form2(); 
form2.Show(); 
form2.WhateverYouWantToAccess 

這就是說,如果你只是想從用戶那裏得到的文件路徑,你想使用OpenFileDialog類。

private void button1_Click(object sender, System.EventArgs e) 
{ 
    Stream myStream = null; 
    OpenFileDialog openFileDialog1 = new OpenFileDialog(); 

    openFileDialog1.InitialDirectory = "c:\\" ; 
    openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ; 
    openFileDialog1.FilterIndex = 2 ; 
    openFileDialog1.RestoreDirectory = true ; 

    if(openFileDialog1.ShowDialog() == DialogResult.OK) 
    { 
     try 
     { 
      if ((myStream = openFileDialog1.OpenFile()) != null) 
      { 
       using (myStream) 
       { 
        // Insert code to read the stream here. 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); 
     } 
    } 
} 
+0

不,這不是肖恩所問的。一般來說,他想知道如何解決不同形式之間的溝通問題。雖然我同意這是一個快速解決方法 - 只需將OpenFileDialog調用放入Sean的「form1」中即可 - 但它並沒有真正回答這個問題。 –

+0

好的,但正如我所說的那部分我知道該怎麼做,其訪問回到主要形式,這是我的問題。 Thx雖然現在我看到如何處理錯誤。 –

+0

@LarsKemmann * [嘆氣] *好的,我會在我的回答中加入一些內容。但是,我不會建議有人創建自定義表單來獲得路徑。 –