Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XSLT

TaskListManager

1.03/5 (13 votes)
13 Mar 2008CPOL2 min read 1   1.2K  
In a cumbersome daily schedule, only tools like this can help us to be a little bit organized.

Introduction

TaskManager is a personal information manager (PIM). It's a tool for managing any kind of personal information such as tasks, events, contacts, favorites, and web links which can be browsed on the same form. It can be used as a mind stimulator, and a self-analysis and self-improvement tool.

In TaskManager, there is no database used; all the relevant information is stored in XML files. It can be one of the best examples of inter-operability of two XML files.

We need not to install a database for using this application.

Task_1.JPG

There are mainly three sections:

Task management: Alerts for pending tasks. Add, Remove, Edit, and Export Task List as HTML or Excel file. For adding or editing the task list, we need to click the Task button in the left pane.

Task_2.JPG

All pending tasks will be displayed as a tooltip in the tray icon. On clicking the tool tip, the user can display the main form.

Contacts management: View contacts as a tree view, easy navigation, adding and deleting contacts. Create groups for all the contacts.

Contacts.JPG

Internet Favorites: Fetching all the folders and links from Internet Explorer Favourite list and displaying it as a treeview. Navigation of the favourite node and displaying the page in a web browser of the same form. Once the application is installed, it will fetch the favourites at runtime.

Fav.JPG

Using the code

I have tried to make it self explanatory and hierarchal. The main classes are: TreeViewSerializer.cs, ContactForm.cs, and TaskManagerForm.cs.

The method below will take care of adding a task in the tasks table of the TaskList XML file.

C#
/// <summary>
/// Utility method to update the visual representation of
/// the tasks (the CheckedListBox) with a new or updated row.
/// </summary>
/// <param name="rowIndex">Index of modifed row, or -1 for new row</param>
/// <param name="row">Row object from the DataTable</param>
private void UpdateDisplayWithRow(int rowIndex, TasksDataSet.TasksRow row)
{
    string title, format = "{0} - Due: {1:d}";

    title = string.Format(format, row.TaskTitle, row.TaskDueDate);

    if (rowIndex == -1)
    {
        tasksCheckedListBox.Items.Add(title, row.TaskComplete);
    }
    else
    {
        // Remove the old value, add a new one, set the checkbox
        tasksCheckedListBox.Items.RemoveAt(rowIndex);
        tasksCheckedListBox.Items.Insert(rowIndex, title);
        tasksCheckedListBox.SetItemChecked(rowIndex, row.TaskComplete);
    }
}

/// <summary>
/// Loads the entries using XML deserialization
/// </summary>
public void LoadEntries()
{
    try
    {
        XmlSerializer s = new XmlSerializer(typeof(TasksDataSet));
        TextReader r = new StreamReader("TaskList.xml");
        ds = (TasksDataSet)s.Deserialize(r);
        r.Close();

    }
    catch
    {
        ds = new TasksDataSet();
    }

    foreach (TasksDataSet.TasksRow row in ds.Tasks)
    {
        UpdateDisplayWithRow(-1, row);
    }
}

/// <summary>
/// Saves the entries using XML serialization
/// </summary>
public void SaveEntries()
{
    try
    {
        XmlSerializer s = new XmlSerializer(typeof(TasksDataSet));
        TextWriter w = new StreamWriter("TaskList.xml");
        s.Serialize(w, ds);
        w.Close();
    }
    catch( Exception x )
    {
        appNotifyIcon.ShowBalloonTip(8000,
            "Bh@nu's - Task Manager",
            "Tasks could not be saved.\n" + x.Message, ToolTipIcon.Error);
    }
}

The CheckTaskDates() method will check the expiry of tasks in a task list. All the pending tasks will be displayed as a tooltip on the tray icon every minute.

C#
/// <summary>
/// Scans the list of tasks. Any incomplete tasks due
/// yesterday or earlier are appended to a buffer for
/// display in the tooltip.
/// </summary>
private void CheckTaskDates()
{
    // StringBuilder is more efficient than string concatentation
    StringBuilder buffer = new StringBuilder();

    // Iterate over each task in the DataSet
    foreach (TasksDataSet.TasksRow row in ds.Tasks)
    {
        // Compare date and completed flag
        if ((DateTime.Now.Date > row.TaskDueDate) && !row.TaskComplete)
        {
            buffer.Append(row.TaskTitle).Append(", Due: ");
            buffer.AppendFormat("{0:d}", row.TaskDueDate).Append('\n');
        }
    }

    // If the buffer is not empty, there is at least one
    // task to display
    if (buffer.Length > 0)
    {
        // Display an Info balloon tip for 8 seconds
        appNotifyIcon.ShowBalloonTip(8000, 
            "bh@nu's - Task Manager", 
            buffer.ToString(), ToolTipIcon.Info);
    }
}

Another important method is there in the ContactForm class. This method will take care of adding new contacts in two XML files along with its unique group and ID. One XML file will contain the treeview data and the other one will contain the details. I have made these two XML files for ease of displaying the treeview.

C#
private void btnUpdate_Click(object sender, System.EventArgs e)
{
    TreeViewSerialization.TreeViewSerializer objTreeViewSerializer = 
                    new TreeViewSerialization.TreeViewSerializer();
    //objTreeViewSerializer.SerializeTreeView(this.treeView_Contacts,
    //       Application.StartupPath + "\\..\\..\\bhanu.xml");
    objTreeViewSerializer.SerializeTreeView(this.treeView_Contacts, 
                          Application.StartupPath + "\\bhanu.xml");

    bool bAddNew = (m_iContactID == 0) ? true : false;

    bool bContinue = true;

    try
    {
        string sFullName = txt_Name.Text;
        string sCellPhone = txt_Cell.Text;
        string sHomePhone = txt_Home.Text;
        string sEmail = txt_Email.Text;
        string sEmail2 = txt_Email2.Text;
        string sAddress = txt_Address.Text;
        string sCity = txt_City.Text;
        string sState = cmb_State.Text;
        string sZip = txt_Zip.Text;
        string sBDay = dt_DateTimePicker.Value.ToLongDateString();

        if( sFullName == "" || sCellPhone == "" || 
            sHomePhone == "" || sEmail == "" || 
            sEmail2 == "" || sAddress == "" || 
            sCity == "" || sState == "" ||
            sZip == "" || sBDay == "" )
        {
            MessageBox.Show( "You must have valid data in each field before" + 
                             " you may\nadd this contact to your contact's list.", 
                             "Validation Error...", MessageBoxButtons.OK, 
                             MessageBoxIcon.Exclamation );
            bContinue = false;
        }

        if( bContinue )
        {
            if( bAddNew == true )
            {
                AddContact( m_XmlDocument, m_iNextID, sFullName, 
                    sCellPhone, sHomePhone, sEmail, sEmail2, sAddress,
                    sCity, sState, sZip, sBDay );
          
                AddContactToCombo( m_iNextID, sFullName );
          
                m_iNextID++;
            }
            else
            {
                UpdateContact( m_XmlDocument, m_iNextID, sFullName, 
                    sCellPhone, sHomePhone, sEmail, sEmail2, sAddress,
                    sCity, sState, sZip, sBDay );
            }
    
            m_XmlDocument.Save( m_sXmlFileName );
        }
    }
    catch( Exception exception )
    {
        MessageBox.Show( exception.Message );
    }
}

private void treeView_Contacts_AfterSelect(object sender, TreeViewEventArgs e)
{
    AddNewContact();
    if (treeView_Contacts.SelectedNode.Text == "Friends" || 
        treeView_Contacts.SelectedNode.Text == "Work")
    {
        return;
    }
    else
    {
        this.txt_Name.Text = this.treeView_Contacts.SelectedNode.Text;

        string strEmail = string.Empty;
        XmlDocument xmlContacts = new XmlDocument();

        xmlContacts.Load(Application.StartupPath +"\\My_Contacts.xml");
                
        foreach (XmlNode xmlItem in xmlContacts)
        {
            foreach (XmlNode newnode in xmlItem)
            {
                if (newnode["FullName"].InnerText == 
                    this.treeView_Contacts.SelectedNode.Text)
                {
                    this.txt_Email.Text = newnode["Email"].InnerText;
                    this.txt_City.Text = newnode["City"].InnerText;
                    this.txt_Home.Text = newnode["HomePhone"].InnerText;
                    this.txt_Zip.Text = newnode["ZipCode"].InnerText;
                    this.txt_Email2.Text = newnode["Email2"].InnerText;
                    this.txt_Address.Text = newnode["StreetAddress"].InnerText;
                    this.cmb_State.Text = newnode["State"].InnerText;
                    this.dt_DateTimePicker.Text = newnode["BDay"].InnerText;
                    this.txt_Cell.Text = newnode["CellPhone"].InnerText;

                }
            }
        }
    }
}

Displaying Internet Favorites is quite simple, and there are only a few methods for displaying the whole stuff. I'm writing those methods as it is.

C#
private bool LoadWebSitesTree()
{
    bool result = false;
    try
    {
        Cursor = Cursors.WaitCursor;
        string favFolderPath = 
          Environment.GetFolderPath(Environment.SpecialFolder.Favorites);

        // Disables any redrawing of the tree view till we are done
        tvWebSites.BeginUpdate();

        LoadFavFromFolder(new DirectoryInfo(favFolderPath), webSitesRootNode);
        LoadFavFromPath(favFolderPath, webSitesRootNode);

        result = true;
    }
    catch (Exception exp) 
    {
        //DebugLog.Instance.REPORT(exp); 
    }
    finally
    {
        Cursor = Cursors.Default;
        tvWebSites.EndUpdate();
    }

    return result;
}

private void LoadFavFromFolder(DirectoryInfo curDirInfo, TreeNode curNode)
{
    try
    {
        TreeNode newNode;

        foreach (DirectoryInfo dirInfo in curDirInfo.GetDirectories())
        {
            if (curNode == null)
                newNode = tvWebSites.Nodes.Add(dirInfo.Name);
            else
                newNode = curNode.Nodes.Add(dirInfo.Name);

            if (dirInfo.GetDirectories().Length == 0)
                LoadFavFromPath(dirInfo.FullName, newNode);
            else
                LoadFavFromFolder(dirInfo, newNode);
        }
    }
    catch (Exception exp) 
    { 
        //DebugLog.Instance.REPORT(exp); 
    }
}

private void LoadFavFromPath(string curPath, TreeNode curNode)
{
    try
    {
        DirectoryInfo curDirInfo = new DirectoryInfo(curPath);

        foreach (FileInfo objFile in curDirInfo.GetFiles("*.url"))
        {
            TreeNode newNode = new TreeNode();

            string fileName = objFile.FullName;
            newNode.Tag = GetURLValue(fileName);
            newNode.Text = Path.GetFileNameWithoutExtension(fileName);
            newNode.ImageIndex = 2;
            newNode.SelectedImageIndex = 2;

            if (curNode == null)
                tvWebSites.Nodes.Add(newNode);
            else
                curNode.Nodes.Add(newNode);
        }
    }
    catch (Exception exp) 
    { 
        //DebugLog.Instance.REPORT(exp); 
    }
}

//    Reading favorites file as INI file getting the value of URL=
private string GetURLValue(string fileName)
{
    string strURL = null;
    StreamReader reader = null;
    try
    {
        reader = new StreamReader(fileName);
        string fileLine;
        int iIndex = -1;
        while ((fileLine = reader.ReadLine()) != null)
        {
            if (fileLine != null)
            {
                if ((iIndex = fileLine.IndexOf("URL=")) >= 0)
                {
                    strURL = fileLine.Substring(iIndex + 4);
                    break;
                }
            }
        }
    }
    catch (Exception exp) 
    { 
        //DebugLog.Instance.REPORT(exp); 
    }
    finally
    {
        try { if (reader != null) reader.Close(); }
        catch (Exception exp) 
        { 
            //DebugLog.Instance.REPORT(exp);
        }
    }

    return strURL;
}

ToDo

  1. Printing support in task grid.
  2. User name and password collection after authentication.
  3. Text decoration.

Cheers!!!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)