Tuesday, March 30, 2010

C#: Xml Writer - Applying XML writer settings

Hi People,

I have seen that at times we need to generate XML using code. This is in contrast to web services, where in XML is generated by the compiler. In this post I would like to give some pointers about creating XML files using C# - the "XmlWriter" class. Consider the following piece of code:

XmlWriter xml = XmlWriter.Create(@"c:\file.xml");


This would instantiate a XML writer and you could use various commands like xml.WriteStartElement(...), xml. WriteValue(..), xml.WriteEndElement() to construct the XML file dynamically. But there is a problem w/ this. A file created w/ such an instance of XmlWriter (xml) would like this:

<?xml version="1.0" encoding="utf-8"?><Users><User><Name>user1</Name></User><User><Name>user2</Name></User><User><Name>user3</Name></User></Users>


But, we may expect the XML file to have some line breaks, indentation to make it readable to others (though XML is not meant for that! ;) ). For this we need to apply some XML writer settings using the "XmlWriterSettings" class as shown below:


XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.NewLineOnAttributes = true;
xmlWriterSettings.Indent = true;


Now the XmlWriter would be instantiated as:

XmlWriter xml = XmlWriter.Create(path, xmlWriterSettings);


With this the XML generated would be indented, with line breaks as appropriate! Check out the final output after the addition settings:

<?xml version="1.0" encoding="utf-8"?>
<Users>
<User>
<Name>user1</Name>
</User>
<User>
<Name>user2</Name>
</User>
<User>
<Name>user3</Name>
</User>
</Users>


Check out the code in full:

void Main()
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.NewLineOnAttributes = true;
xmlWriterSettings.Indent = true;

XmlWriter xml = XmlWriter.Create(@"C:\file.xml", xmlWriterSettings);

xml.WriteStartElement("Users");

foreach (string client in new string[] {"user1","user2","user3"})
{
xml.WriteStartElement("User");

xml.WriteStartElement("Name");
xml.WriteValue(client);
xml.WriteEndElement();

xml.WriteEndElement();
}

xml.WriteEndElement();

xml.Close();
}

Saturday, March 20, 2010

S.O.L.I.D C# Code - Writing less code to carry out an activity unlike conventional methods (Comparison)

Hey All!

I am back w/ a C# post at last! Been while since I posted anything related to C#. Its 1'o clock, so I may have to edit this post later. I was reading some posts about S.O.L.I.D C# principles and I thought that I should post something about that. We may be (are) unknowingly using a lot of S.O.L.I.D principles in our day-to-day life probably.

Check out the following example. You would be able to notice clearly that S.O.L.I.D code uses much lesser amount of code to accomplish the same task that conventional code does. Keep in mind that List<T> implements the IEnumerable<T> and IEnumerable interface, but, ArrayList only implements IEnumerable. And, to say the least, both List<T> and ArrayList are extremely useful data structures (I feel!).

public class Content
{
public int a;
public string b;
}

public class EnumQu
{
public ArrayList arrList = null;
public List<Content> list = null;

private static void print(string message)
{
Console.WriteLine("");
Console.WriteLine(message);
Console.WriteLine("");
}

public void loadData()
{
arrList = new ArrayList();
list = new List<Content>();

for (int i = 0; i < 10; i++)
{
Content c = new Content();
c.a = (i + 1);
c.b = "String " + (i + 1);

arrList.Add(c);
list.Add(c);
}
}

public void arrayListTests()
{
// Display the items in ArrayList
// ArrayList implements IEnumerable but not IEnumerable<T>
// so .ForEach cannot be invoked

// S.O.L.I.D code to display (at least partially)
print("Select (S.O.L.I.D):");

var query = (from Content c in arrList select new { c });

foreach (var q in query) { Console.WriteLine(q.c.a + " - " + q.c.b); }

// S.O.L.I.D code to query for a value
print("Select - Single (S.O.L.I.D):");

var query_sel = (from Content c in arrList where c.a == 5 select new { c });

foreach (var q in query_sel) { Console.WriteLine(q.c.a + " - " + q.c.b); }

// Conventional C# code
print("Select:");

foreach (Content c in list)
{
Console.WriteLine(c.a + " - " + c.b);
}

print("Select - Single:");

foreach (Content c in list)
{
if (c.a == 5)
{
Console.WriteLine(c.a + " - " + c.b);
}
}
}

public void listTests()
{
// Display the items in List<T>
// List<T> implements IEnumerable<T> so .ForEach can be invoked

// S.O.L.I.D code
print("Select (S.O.L.I.D):");

list.ForEach(delegate(Content c){ Console.WriteLine(c.a + " - " + c.b); });

// S.O.L.I.D code to query for a value
print("Select - Single (S.O.L.I.D):");

List<Content> cList = list.Where(c => c.a == 5).ToList();

cList.ForEach(delegate(Content c){ Console.WriteLine(c.a + " - " + c.b); });

// Conventional C# code
print("Select:");

foreach (Content c in list)
{
Console.WriteLine(c.a + " - " + c.b);
}

print("Select - Single:");

foreach (Content c in list)
{
if (c.a == 5)
{
Console.WriteLine(c.a + " - " + c.b);
}
}
}

public static void Main(string[] args)
{
EnumQu enumQu = new EnumQu();
enumQu.loadData();
enumQu.arrayListTests();
enumQu.listTests();
}
}

As said before, I may have to add more information in here!! See you soon with another post!!!

Happy coding!

~ Karthik

Thursday, March 11, 2010

Flex/ActionScript - Item Renderers Issue (Items not being rendered as required)

Hi People!

It's been a very very long time since I posted something! So here is some Flex/ActionScript stuff. (Some C# stuff is coming soon ;))!

This post is about correcting the issue encountered while using item renderers in DataGrids. I am not a UI guy and this post mainly concentrates on how to solve and not any fancy stuff. Coming to the point, when using datagrids in Flex, the default "rowCount" attribute would be roughly 7/8. Assume you are setting the "rowCount" attribute to "10". Now when Flex renders the data grid, only 10 itemRenderer instances are created as the user will initially be able to view only 10 rows. And if you are using itemRenderers you are most likely to render them using multiple properties from the dataProvider. Consider the following data grid column:

<mx:DataGridColumn headerText="Attachments" dataField="Id and HasAttachment and ServerID" itemRenderer="renderer.AttachmentColRenderer" />

Here the item renderer "AttachmentColRenderer" would be using the following properties from the dataProvider: Id, HasAttachment, ServerID. I got in to a problem while using item renderers. The issue was that, the first 10 items were displayed as per the requirement. But while scrolling/paging I noticed that the items rendered were not according to what they should be. For example, I had to make a link button visible if there was an attachment and vice versa. But for some items the link button appeared even though there were no corresponding downloads. Before using this solution I was using the "creationComplete" event to manipulate the controls as required.

The issue was that Flex reuses the instances of the item renderers created initially. And so, the data wouldn't be set during reuse causing this issue. To overcome this add the following in the item renderer


<mx:Script>
<![CDATA[
// Over ride the "set" method so that every instance gets appropriate data
override public function set data(value:Object):void
{
// At times you 'may' get a null
if (value != null)
{
// super.data would normally hold the data for this instance
super.data = value;

// Process the data as per requirements from this point
if (super.data.HasAttachment.toString() == "true")
{
lnkDownload.visible = true;
}
else
{
lnkDownload.visible = false;
}
}
}
]]>
</mx:Script>

Here I need to override the set data method, so that the data that corresponds this particular instance is being set. After this the items were rendered as expected. If you are a flex person, the above snippet would immediately make sense, so I guess no explanation is needed!

Happy coding!

~ Karthik