Wednesday, July 18, 2012

Windows Presentation Foundation #WPF Example: Send notes in an Email C#

At my workplace we are supposed to send notes about our work on a weekly basis to our manager.

So when it was time for my annual review I wanted retrieve all my projects notes for the entire year.I always copy the notes I send to my manager in a text file so that at the mid and annual review I would have all the notes in one single file.


New hires who are not aware of the processes did not have all their notes in place and had to dig through their emails to get all the notes.The mailbox could only save up to 6 months of mails so the notes older than 6 months were lost.

So I decided to write this tool for learning something new i.e Windows Presentation Foundation.

Very basic requirements:



  • Application would have a placeholder for entering notes (plain text).
  • A button to save the notes to a text file and email the notes to manager.
  • A window to display notes and buttons to navigate through all notes.
Create a new project and choose WPF Application


















When created the project consists of App.xaml,MainWindow.xaml files. Add a WPF window i.e LoadFileWindow


















Add an App.Config to hold all the keys used in the application.My configuration file looks like this

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="FROM_EMAIL" value="myname@mycompany.com"/>
    <add key="TO_EMAIL" value="myname@mycompany.com,mymanager@mycompany.com"/>
    <add key="FILE_PATH" value="C:\Status_2012.txt"/>
  </appSettings>
</configuration>

Add controls to the forms based on the requirements outlined at the beginning

MainWindow with textbox to hold the email address,richtextbox to hold the notes,notes button to open all notes windows and send button to save and send an email to the manager















LoadfileWindow with richtextbox to display notes,previous,next buttons to shift through notes and close button to close the window.















Next add code to the button events.

MainWindow.xaml.cs

using System;
using System.Windows;
using System.Windows.Documents;
using System.IO;
using System.Configuration;

namespace StatusNotes
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DateLabel.Content = "Date:" +DateTime.Now.ToString();
            EmailTextBox.Text = ConfigurationManager.AppSettings["TO_EMAIL"];
        }

        private void SendMail_Click(object sender, RoutedEventArgs e)
        {
            TextRange textRange = new TextRange(StatusRichTextBox.Document.ContentStart,StatusRichTextBox.Document.ContentEnd);
            WriteToFile(textRange);
            SendMail(EmailTextBox.Text, "Status Notes for " + DateTime.Now.ToString(), textRange.Text, false);
            MessageBox.Show(Application.Current.MainWindow,"Your status notes has been emailed to your manager.","Confirmation",MessageBoxButton.OK);
            StatusRichTextBox.Document.Blocks.Clear();
        }

        private void ShowAllStatusButton_Click(object sender, RoutedEventArgs e)
        {
            var newWindow = new LoadFileWindows();
            newWindow.ShowDialog();
        }

        private void WriteToFile(TextRange textRange)
        {
            using (StreamWriter oWriter = new StreamWriter(ConfigurationManager.AppSettings["FILE_PATH"], true))
            {
                oWriter.WriteLine(DateTime.Now.ToString());
                oWriter.WriteLine("*****************************************************************************");
                oWriter.WriteLine(textRange.Text);
                oWriter.WriteLine("*****************************************************************************");
                oWriter.Write("$");
            }
        }

        private void SendMail(string p_sEmailTo, string subject, string messageBody, bool isHtml)
        {
            try
            {
                string sEmailTo = p_sEmailTo;
                string sEmailFrom = ConfigurationManager.AppSettings["FROM_EMAIL"];

                string DEFAULT_MAIL_SERVER = "DefaultMailServerName";
                System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(sEmailFrom, sEmailTo);
                msg.From = new System.Net.Mail.MailAddress(sEmailFrom, "Status Notes");
                msg.IsBodyHtml = isHtml;
                msg.Subject = subject;
                msg.Body = messageBody;

                System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(DEFAULT_MAIL_SERVER);
                client.Send(msg);
            }
            catch
            {

            }
        }
    }
}

LoadFileWindow.xaml.cs

using System.Collections.Generic;

using System.Linq;

using System.Windows;

using System.Windows.Documents;

using System.IO;

using System.Configuration;

namespace StatusNotes
{
    /// <summary>
    /// Interaction logic for LoadFileWindows.xaml
    /// </summary>
    public partial class LoadFileWindows : Window
    {
        public  int iCounter = 0;
        public  int iMaxcounter = 0;
        public  List<string> sStatusList = new List<string>();

        public LoadFileWindows()
        {
            
            InitializeComponent();
            using (StreamReader oReader = new StreamReader(ConfigurationManager.AppSettings["FILE_PATH"]))
            {
                string sFullText = oReader.ReadToEnd().Trim('\n').Trim('\r');
                sStatusList = sFullText.Split('$').ToList<string>();
                iMaxcounter = sStatusList.Count;
            }
            FlowDocument oFlowDocument = new FlowDocument();
            oFlowDocument.Blocks.Add(new Paragraph(new Run(sStatusList[iCounter])));
            StatusRichTextBox.Document = oFlowDocument;
        }

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

        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            if (iCounter == 0)
                MessageBox.Show(Application.Current.Windows[1], "No more status notes beyond this point.Use the > button to scroll forward !", "Alert", MessageBoxButton.OK);
            else
            {
                iCounter--;
                StatusRichTextBox.Document.Blocks.Clear();
                FlowDocument text = new FlowDocument();
                text.Blocks.Add(new Paragraph(new Run(sStatusList[iCounter])));
                StatusRichTextBox.Document = text;
            }
        }

        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            if (iCounter == iMaxcounter-2)
                MessageBox.Show(Application.Current.Windows[1],"No more status notes beyond this point.Use the < button to scroll back !","Alert",MessageBoxButton.OK);
            else
            {
                iCounter++;
                StatusRichTextBox.Document.Blocks.Clear();
                FlowDocument text = new FlowDocument();
                text.Blocks.Add(new Paragraph(new Run(sStatusList[iCounter])));
                StatusRichTextBox.Document = text;
            }
        }
    }
}

Output:



















Click on the Notes button.This is bring up the below window.Use the <,> buttons to shift through all your notes which are saved in the text file on your machine.





2 comments:

aviotron said...

Dude! You rock !
This app was just fantastic, thanks for a good tutorial.

One question: Can we write pdf file instead of txt file ? So that pictures can be saved along with the text.

Virtuoso said...

Sure you can but you would have to use a third party library for converting the content into a pdf document.See here for more instructions ( http://stackoverflow.com/questions/465433/creating-pdf-files-at-runtime-in-c-sharp )