Tag Archives: C# - Page 4

Extension method to create CSV from List collection

A quick one to share:

I needed to a method to quickly convert a List<string> to a plain comma delimited string. So I created this little Extension class:

public static class ListEx
{

public static string ToCSVString(this List<string> l)
{

StringBuilder sb = new StringBuilder();
if (l != null)
{

l.ForEach(li => sb.Append(li + “, “));

}
return sb.ToString().Trim(‘ ‘, ‘,’);

}

}

Of course this is still very specific to string collections only. I could have created something that does the same to say a List<T> list that is more generic but that I’ll leave for another day.

[Update]

While I’m at it – here is the opposite method:

public static List<string> ToListFromCSVString(this string s, bool ordered = false)
{

List<string> list = new List<string>();
if (s != null && s.Trim().Length > 0)
{

if (ordered)

list.AddRange((from sitem in s.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries)
orderby sitem
select sitem.Trim()).ToArray());

else

list.AddRange((from sitem in s.Split(new char[] { ‘,’ }, StringSplitOptions.RemoveEmptyEntries)
select sitem.Trim()).ToArray());

}

return list;

}

XmlElementEx – a few XmlElement extension methods

I thought I’d just share a few extension methods I created for myself to handle a hew things with the XmlElement, XmlNode and XmlDocument classes of System.Xml namespace.

These include:

  • ReadXmlElementAttr
  • CreateAttributeWithValue
  • SetAttributeValue
  • AppendElementWithText
  • AppendElementWithCDATA
using System.Xml;

    public static class XmlElementEx
    {
        public static string ReadXmlElementAttr(this XmlElement e, string attrName, string defaultValue = "")
        {
            try
            {
                if (e.HasAttribute(attrName))
                    return e.Attributes.GetNamedItem(attrName).Value;
            }
            catch { }
            return defaultValue;
        }
        public static string ReadXmlElementAttr(this XmlNode e, string attrName, string defaultValue = "")
        {
            return ReadXmlElementAttr((XmlElement)e, attrName, defaultValue);
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, bool value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, int value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }
        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, long value)
        {
            return xml.CreateAttributeWithValue(attrName, value.ToString());
        }

        public static XmlAttribute CreateAttributeWithValue(this XmlDocument xml, string attrName, string value)
        {
            XmlAttribute attr;
            attr = xml.CreateAttribute(attrName);
            attr.Value = value;
            return attr;
        }
        public static XmlAttribute SetAttributeValue(this XmlNode e, string attrName, string value)
        {
            return SetAttributeValue((XmlElement)e, attrName, value);
        }
        public static XmlAttribute SetAttributeValue(this XmlElement e, string attrName, string value)
        {
            if (e.HasAttribute(attrName))
                e.Attributes[attrName].Value = value;
            else
                e.Attributes.Append(CreateAttributeWithValue(e.OwnerDocument, attrName, value));
            return e.Attributes[attrName];
        }

        public static XmlElement AppendElementWithText(this XmlElement e, string elementName, string text)
        {
            XmlElement newElement = e.OwnerDocument.CreateElement(elementName);
            newElement.InnerText = text;
            e.AppendChild(newElement);
            return newElement;
        }
        public static XmlElement AppendElementWithCDATA(this XmlElement e, string elementName, string cdataText)
        {
            XmlElement newElement = e.OwnerDocument.CreateElement(elementName);
            XmlCDataSection commentNode = e.OwnerDocument.CreateCDataSection(cdataText);
            newElement.AppendChild(commentNode);
            e.AppendChild(newElement);
            return newElement;
        }
    }

 

Is it my time or not?

Sounds like another philosophical question but no, you can relax. This is another developmental (yes almost mental) posting.

Say you need to create a piece of functionality that must only operate within a predefined time period of a day – call it a ‘service window’. It could be that you may even need several of these ‘windows’ per day – i.e. if there is a pause period inside the day and work must be processed before (up until) and after the pause.

For this kind of functionality I created a ‘ServiceWindows’ class. It basically host a list of ‘from’ and ‘to’ times plus methods that makes it possible to find out if a specified time is somewhere ‘inside’ or ‘outside’ any ‘service window’. Additionally the class can be ‘populated’ from an xml config string so it can be used in applications that operates from xml config files.

So without much further chit-chatting here is the guts of the class (not for sensitive readers 😉

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

    public class ServiceWindow
    {
        public ServiceWindow(DateTime from, DateTime to)
        {
            From = from;
            To = to;
        }
        public DateTime From { get; set; }
        public DateTime To { get; set; }
    }

    public class ServiceWindows
    {
        private List<ServiceWindow> times = new List<ServiceWindow>();
        public List<ServiceWindow> Times { get { return times; } }

        public void AddTimeWindow(DateTime fromTime, DateTime toTime)
        {
            times.Add(new ServiceWindow(fromTime, toTime));
        }
        public bool IsInTimeWindow()
        {
            return IsInTimeWindow(DateTime.Now);
        }
        public bool IsInTimeWindow(DateTime nowTime)
        {
            if (times.Count == 0)
                return true;
            else
                return (from t in times
                        where t.From.TimeOfDay <= nowTime.TimeOfDay &&
                              t.To.TimeOfDay >= nowTime.TimeOfDay
                        select t).Count() > 0;
        }

        public void CreateFromConfig(string config)
        {
            if (config.Length > 0)
            {
                times.Clear();
                XmlDocument configXml = new XmlDocument();
                configXml.LoadXml(config);
                XmlElement root = configXml.DocumentElement;
                foreach (XmlNode windowItem in root.SelectNodes("window"))
                {
                    try
                    {
                        DateTime fromTime = DateTime.Parse(windowItem.ReadXmlElementAttr("from", "00:00:01"));
                        DateTime toTime = DateTime.Parse(windowItem.ReadXmlElementAttr("to", "23:59:59"));
                        times.Add(new ServiceWindow(fromTime, toTime));
                    }
                    catch { }
                }
            }
        }
        public string ToConfig()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<serviceWindows>");
            if (times.Count > 0)
                foreach (ServiceWindow timeWindow in times)
                    sb.AppendLine(string.Format("<window from=\"{0}\" to=\"{1}\" />",
                              timeWindow.From.ToString("HH:mm:ss"),
                              timeWindow.To.ToString("HH:mm:ss")));

            sb.AppendLine("</serviceWindows>");
            return sb.ToString();
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (times.Count > 0)
                foreach (ServiceWindow timeWindow in times)
                    sb.Append(string.Format("{0} to {1} and ",
                           timeWindow.From.ToString("HH:mm:ss"),
                           timeWindow.To.ToString("HH:mm:ss")));
            else
                sb.Append("None");
            return sb.ToString().Trim(' ', 'a', 'n', 'd');
        }
    }

I noticed that I included an XmlNode extension method (ReadXmlElementAttr) that I defined elsewhere but all it does is to read an xml element attribute or provide a default value if not found. I’ll list that class here on my blog too soon.

Waiting for your exit

With a heading like this the post could be mistaken for something more philosophical but fortunately this is a plain developmental posting 🙂

Suppose you have some program that does some work and then have to ‘sleep’ for a while before doing some more work – like a service checking or polling stuff. You can simply use something like a Thread.Sleep() but that also means the thread cannot do or respond to anything else during that time – like the program or service stopping. That would mean the stopping process has to wait until the ‘sleeping’ thread becomes active again.

A solution to this is by having a variable or property that indicates if the program or service is still running and having the ‘waiting’ routine wait in little ‘jumps’ checking the ‘IsRunning’ variable each time and then waiting a little bit more until the full ‘sleeping’ period time is done.

private void BackgroundWaitIsPolling(int nextWaitInterval)
{
   int waitTimeRemaining;
   int decrementBy = 2000;
   if (IsRunning)
   {
       try
       {
           if ((nextWaitInterval <= decrementBy) && (nextWaitInterval > 0))
           {
               Thread.Sleep(nextWaitInterval);
           }
           else
           {
               waitTimeRemaining = nextWaitInterval;
               while (IsRunning && (waitTimeRemaining > 0))
               {
                  if (waitTimeRemaining <= decrementBy)
                  {
                      waitTimeRemaining = 0;
                  }
                  else
                  {
                      waitTimeRemaining -= decrementBy;
                  }
                  if (decrementBy > 0)
                  {
                      Thread.Sleep(decrementBy);
                  }
               }
           }
        }
        catch { }
   }
}

 

Extending the TreeView control

Here is a little Extension class to the TreeView control. I created it to add some new functionality that is not available in the base control. It is based on the System.Windows.Forms namespace TreeView but probably can be use relatively easy without too much modification on WPF as well (haven’t tried it yet)

public static class TreeViewEx
    {
        public static int CheckedCount(this TreeView tvw)
        {
            int count = 0;
            count = (from TreeNode n in tvw.Nodes
                     where n.Checked
                     select n).Count();
            foreach (TreeNode childNode in tvw.Nodes)
            {
                count += CheckedCount(childNode);
            }

            return count;
        }
        public static int CheckedCount(this TreeNode parentNode)
        {
            int count = 0;
            count = (from TreeNode n in parentNode.Nodes
                     where n.Checked
                     select n).Count();
            foreach (TreeNode childNode in parentNode.Nodes)
            {
                count += CheckedCount(childNode);
            }
            return count;
        }
        public static List<TreeNode> CheckedNodes(this TreeView tvw)
        {
            List<TreeNode> checkedNodes = new List<TreeNode>();
            foreach(TreeNode node in (from TreeNode n in tvw.Nodes
                         select n))
            {
                if (node.Checked)
                    checkedNodes.Add(node);
                checkedNodes.AddRange(node.CheckedNodes().ToArray());
            }
            return checkedNodes;
        }
        public static List<TreeNode> CheckedNodes(this TreeNode parentNode)
        {
            List<TreeNode> checkedNodes = new List<TreeNode>();
            foreach (TreeNode node in (from TreeNode n in parentNode.Nodes
                                           select n))
            {
                if (node.Checked)
                    checkedNodes.Add(node);
                checkedNodes.AddRange(node.CheckedNodes().ToArray());
            }
            return checkedNodes;
        }
        public static void ExpandAllParents(this TreeNode node)
        {
            TreeNode parent = node.Parent;
            while (parent != null)
            {
                parent.Expand();
                parent = parent.Parent;
            }
        }
    }

QuickMon 2

A quick follow-up on my QuickMon application. I’ve now managed to get a basic working application that performs some simple monitoring of 4 different types of agents (ping, file count, services and BizTalk suspended instance count). Also it includes the first notifier agent that simply logs to a plain text file.

The full architecture is a bit complicated to explain in a simple post so I’ll have to start working on a much more detail blog posting to explain it all.

Other than the documentation the next steps are to test its stability, improve error handling and adding the other basic agents I planned to make it useful.

Basic string to integer conversion extensions

Sometimes the more simpler things in life really help. Take the following couple of .Net extensions posted to CodeProject. Some of these will make (developer) life a bit easier.

http://www.codeproject.com/Tips/211015/Basic-string-to-integer-conversion-extensions

Console.ReadKey with timeout

There have been multiple times I wished I had a method for this. Often when you are testing things using a plain console application you want to view some output but not have to wait forever (using something like Thread.Sleep) or every time needing to press the ‘Any’ key 😉

Actually I’m a bit surprised .Net hasn’t got something like this built in yet but since it doesn’t I had to create one myself. I created a utility class with a single method to accomplish this. I thought about using an extension method but since the Console class is itself static extension methods does not work for it.

public static class ConsoleHelper
{

public static ConsoleKeyInfo ReadKeyWithTimeOut(int timeOutMS)
{

DateTime timeoutvalue = DateTime.Now.AddMilliseconds(timeOutMS);

while (DateTime.Now < timeoutvalue)
{

if (Console.KeyAvailable)
{

ConsoleKeyInfo cki = Console.ReadKey();
return cki;

}
else
{

System.Threading.Thread.Sleep(100);

}

}
return new ConsoleKeyInfo(‘ ‘, ConsoleKey.Spacebar, false, false, false);

}

}

What this gives you is a method that waits until the specified time-out expires or any (normal) key has been pressed.

Embedding a Form inside another control

This is something I was thinking about at the beginning of my TDI (Tabbed document interface) ‘adventure’ but I didn’t think it would be easy or possible back then. Then I came across a custom tab control (A highly configurable MDI tab control from scratch) that actually allowed you to use plain old WinForms to add to it. The control itself was written in VB and ultimately I abandoned using it but I was intrigued with how it could use a plain WinForm. It actually has some real advantages like.

  • A form you can design easier in the IDE (than a user control).
  • A form can be tested/used separately on it own without being embedded onto something else first.
  • And I had a blank thinking of more reasons…

If you try to just add a Form to another container – like a panel, tabpage etc. and try to run it you would get the error: ‘Top-level control cannot be added to a control.‘. This happens because Forms are marked as Top Level controls. Fortunately, there is a simple way around it. You need to mark the form as not being a ‘Top level control’ like this: (assuming you have a panel called panel1)

Form f = new Form();
f.TopLevel = false;
panel1.Controls.Add(f);
f.Show(); //this is needed to actually have the form display itself inside the container

That will make the form load inside the panel without run-time errors – but it would look ugly if you just leave it like that. To properly ’embed’ it you need to add some more code:

Form f = new Form();
f.TopLevel = false;
f.MdiParent = null;
f.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
f.Dock = DockStyle.Fill;
panel1.Controls.Add(f);
f.Show();

So, there you have it!

Form2 f = new Form2();
            f.TopLevel = false;

Tab control

I’ve come across a tab control that I can customize for my needs in creating a MDI window replacement. It is based on the KRBTabControl article from Karub Yaz?l?m on CodeProject.

I’ve added some built-in context menu that adds a few options for closing a tab, closing all tabs, closing all other tabs and view a list of the available tabs from a modal dialog window. The rest is pretty much the original control except for some enums that I moved around.

My version can be found here.

* Update *

I’ve added an event to the control to fire when a tab page get removed. The code to achieve this looks like this:

public event TabPageRemovedDelegate TabPageRemoved;
private void RaiseTabPageRemoved(TabPageEx tab)
{

if (TabPageRemoved != null)

TabPageRemoved(tab);

}

The ‘RaiseTabPageRemoved’ method then gets called from the main OnMouseClick plus my new context menu events to close tabs.