2013-01-16 132 views
1

我試圖尋找,但沒有找到任何東西,給了我完全是我一直在尋找。我正在創建一個WPF桌面應用程序,最終將有四個或五個窗體。每份表格都會收集通過電子郵件發送的數據。我還創建了一個單獨的類(SendMail),它具有發送電子郵件的代碼。我希望能夠從各種形式的文本框中訪問文本,並通過SendMail類中的方法發送它們。訪問數據

目前,我只設置了幾個字段和下一個頁面,提交和退出按鈕兩種基本形式。我希望能夠從任何頁面提交數據,如果以下任何頁面都不需要填寫。我目前能夠通過內部屬性從SendMail類訪問每個表單,當我點擊第一個表單上的Submit按鈕時,電子郵件正確發送。但是,如果我轉到下一個表單並點擊提交按鈕,我會收到一個「引用未設置爲對象的實例的對象引用」錯誤,以引用第一個表單上的文本框的文本。我假設通過轉到第二種形式,第一種形式的實例不再存在。

我拍了幾張編程類早在大學幾年前,但現在我已經決定要更認真學習對我自己。我讀過幾本書,但只學了幾個月,所以我可能以錯誤的方式接近。任何幫助表示讚賞。

編輯 - 下面是代碼的一些樣品,作爲請求。我從SendMail類中刪除了電子郵件地址/密碼。

第一窗口

public partial class MainWindow : Window 
{ 
    SendMail page1; 

    // Properties to allow access to SendMail. 
    internal string CmbEmail 
    { 
     get { return this.cmbEmail.Text; } 
    } 

    internal string DateWritten 
    { 
     get { return this.dateWritten.Text; } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     page1 = new SendMail(this); 
    } 

    private void btnSubmit_Click_1(object sender, RoutedEventArgs e) 
    { 
     page1.Email(); 
    } 

    private void btnNextPage_Click(object sender, RoutedEventArgs e) 
    { 
     Window1 nextPage = new Window1(this); 
     nextPage.Show(); 
     this.Close(); 
    } 
} 

第二個窗口

public partial class Window1 : Window 
{ 
    SendMail page2; 

    public Window1(MainWindow parent) 
    { 
     InitializeComponent(); 
     page2 = new SendMail(this); 
    } 

    private void btnExit_Click(object sender, RoutedEventArgs e) 
    { 
     this.Close(); 
    } 

    private void btnSubmit_Click(object sender, RoutedEventArgs e) 
    { 
     page2.Email(); 
    } 
} 

的SendMail類

class SendMail 
{ 
    MainWindow page1; 
    Window1 page2; 

    public SendMail(MainWindow form) 
    { 
     page1 = form; 
    } 

    public SendMail(Window1 form) 
    { 
     page2 = form; 
    } 

    public void Email() 
    { 
     NetworkCredential cred = new NetworkCredential("", ""); 
     MailMessage msg = new MailMessage(); 
     msg.To.Add(""); 

     // Send an email to address in the Email field, if not empty. 
     if (page1.CmbEmail != "") // This is the line throwing the error, but only when submitting from the second window. 
     { 
      msg.To.Add(page1.CmbEmail); 
     } 

     msg.From = new MailAddress(""); 
     msg.Subject = "Garment Order " + page1.DateWritten.ToString(); 
     msg.Body = "Test email"; 

     SmtpClient client = new SmtpClient("smtp.gmail.com", 587); 
     client.Credentials = cred; 
     client.EnableSsl = true; 
     client.Send(msg); 
    } 
} 
+0

在這裏發佈您的代碼 – VladL

+0

WPF沒有表格。發佈引發錯誤的行的代碼。 – Paparazzi

+0

告訴我們你試過的東西 – Luv

回答

0

我認爲你是正確的,因爲第一種形式的TextBox不再存在,這是爲什麼你會收到錯誤。這是因爲WPF卸載了不再可見的控件,並且除非它們綁定到DataContext中的某些內容,否則它們中的所有數據都將被遺忘。

我會強烈建議使用MVVM設計模式,如果你用WPF工作。它非常適合這項技術,並且我發現它使代碼保持清潔並易於維護。

在你的情況,我會爲你的整個應用程序的單一ViewModel,並將其包含SubmitCommand和5的數據對象,每個代表從一個「表」

的數據。例如,您MainViewModel看起來像這樣:

public MainViewModel : INotifyPropertyChanged 
{ 
    // Should be full properties that implement INotifyPropertyChanged, 
    // but leaving that out for simplicity right now 
    public ObservableCollection<object> Forms { get; set; } 
    public object CurrentForm { get; set; } 

    public ICommand SubmitCommand { get; set; } 
    // Could also add ICommands for Back and Next buttons as well 

    public MainViewModel() 
    { 
     Forms = new ObservableCollection() 
     { 
      new Form1Data(), 
      new Form2Data(), 
      new Form3Data(), 
      new Form4Data(), 
      new Form5Data() 
     }; 

     CurrentForm = Forms.FirstOrDefault(); 
    } 
} 

而且你的XAML會是這個樣子:

<Window> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type local:Form1Data}"> 
      <local:Form1UserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:Form2Data}"> 
      <local:Form2UserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:Form3Data}"> 
      <local:Form3UserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:Form4Data}"> 
      <local:Form4UserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:Form5Data}"> 
      <local:Form5UserControl /> 
     </DataTemplate> 
    </Window.Resources> 

    <DockPanel> 
     <Button Command="{Binding SubmitCommand}" 
       Content="Submit" DockPanel.Dock="Bottom" /> 

     <ContentControl Content="{Binding CurrentForm}" /> 
    </DockPanel> 
</Window> 

(你可以ALS o在DataTemplates中的XAML中寫出表單控件而不是使用UserControl)

如果您是WPF和MVVM設計模式的新手,我有一個非常有用的simple example on my blog,您可能有興趣閱讀以開始使用它。

編輯

我剛纔看到你的更新問題的代碼,在這裏你的問題是,你有你SendMail類的兩個副本,一個與你的第一個窗口,一個與你的第二個窗口。你需要有一個SendMail類的單個副本,並讓它參考兩個窗口。

雖然就像我在回答開始時所說的那樣,但我認爲這不會起作用,因爲WPF會卸載不可見的UI對象,因此當您的窗口中的任何數據可能會丟失時。

+0

感謝您的廣泛答覆和見解。我對WPF相當陌生,只對MVVM做過少量研究。當我有更多時間時,我會檢查你的博客。它看起來有一些很好的信息。 – jlbridenstine

+0

我不知道爲什麼我沒有想到這一點。我做了必要的更改,現在我可以從兩個窗口提交。再次感謝您的幫助。我仍然要檢查你的博客並更廣泛地研究MVVM,因爲我想學會高效地編寫代碼,但是這對於我試圖用這個應用程序來完成的工作是有效的。 – jlbridenstine

0

看看構造函數。

這將使用第二構造函數(而不是第1頁分配)

page2 = new SendMail(this); 

上面這是一個窗口1

public SendMail(MainWindow form) 
{ 
    page1 = form; 
} 

public SendMail(Window1 form) 
{ 
    page2 = form; 
} 

的窗口1構造函數不分配第1頁。
因此,page1.CmbEmail將拋出一個「對象引用未設置爲對象的實例」。

我認爲當你把它

第2頁=新的SendMail(這一點,父母),你可以用

public SendMail(Window1 form, MainWindow mainWindow) 
    { 
     page2 = form; 
     page1 = mainWindow; 
    } 

解決這個問題。然後,

但是,如果父窗口關閉,則會中斷。
但是,由於父窗口是主窗口,無論如何將關閉所有東西。
因此,不會再有一個Page1提交按鈕失敗。

+0

有道理。謝謝您的幫助。 – jlbridenstine