Showing posts with label CodeCSharp. Show all posts
Showing posts with label CodeCSharp. Show all posts

Thursday, May 07, 2009

Cascading DropDownLists in DetailsView – Databinding error

I came across a requirement to have linked DropdownLists in insert mode of  DetailsView bound to EntityDataSource.

In insert mode of DetailsView one of the fields is bound to a dropdownlist’s selected value.  But the requirement here is values of dropdownlist vary depending on where condition bound to selected value of another dropdown list.

 image

As shown above TaskID is one of the fields. But tasks vary based on project selected. This is achieved by converting TaskField to TemplateField. I have pasted below code for EditTemplate, InsertTemplate and ItemTempalte. In this only TaskID is bound column while project is added manually.

Without doing modifications shown below I was getting error

Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.

This is because upon postback DetailsView control is not re binding to selected value  SelectedValue='<%# Bind("TaskID") %>'

<asp:TemplateField HeaderText="TaskID" SortExpression="TaskID">

<
EditItemTemplate>
<
asp:Label ID="Label3" runat="server" Text='<%# Eval("TaskID") %>'></asp:Label>
</
EditItemTemplate>

<
InsertItemTemplate>
<
asp:DropDownList ID="DropDownList5" runat="server" AutoPostBack="True"
DataSourceID="EntityDataSource5" DataTextField="ProjectName"
DataValueField="ProjectID" Width="100%">
</
asp:DropDownList>
<
asp:EntityDataSource ID="EntityDataSource5" runat="server"
ConnectionString="name=MyEntities" include="Tasks"
DefaultContainerName="MyEntities" EntitySetName="Projects">
</asp:EntityDataSource>
<
br />
<
asp:DropDownList ID="DropDownList4" runat="server"
DataSourceID="EntityDataSource6" DataTextField="TaskDescription"
DataValueField="TaskID" Width="100%">
</
asp:DropDownList>
<
asp:EntityDataSource ID="EntityDataSource6" runat="server"
ConnectionString="name=MyEntities"
DefaultContainerName="MyEntities" EntitySetName="Tasks"
Where="it.ProjectID==@ProjectID" >
<
WhereParameters
>
<
asp:ControlParameter ControlID="DropDownList5" Name
="ProjectID"
Type="Int32" PropertyName
="SelectedValue" />
</
WhereParameters
>
</
asp:EntityDataSource>
</
InsertItemTemplate>

<
ItemTemplate>
<
asp:Label ID="Label3" runat="server" Text='<%# Bind("TaskID") %>'></asp:Label>
</
ItemTemplate>

</
asp:TemplateField>

Also observe highlighted portions where autopostback is set for project dropdownlist and its selectedvalue is bound to DetailsView in where condition of Tasks Dropdownlist. But here TaskID selected value is not bound to TaskID field of DetailsView.

This binding is made in OnItemInserting event handler of DetailsView as shown below

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" CellPadding="4"
DataKeyNames="ResourceID" DataSourceID="EntityDataSource2" ForeColor="#333333"
GridLines="None" Height="50px" Width="125px" OnItemInserted="DetailsView1_ItemInserted"
DefaultMode="Insert" OnItemInserting="DetailsView1_OnItemInserting">

with page behind file containing handler like

protected void DetailsView1_OnItemInserting(object sender, DetailsViewInsertEventArgs e)
{
String TaskID = ((DropDownList)(DetailsView1.FindControl("DropDownList4"))).SelectedValue;
e.Values.Add("TaskID", TaskID);
}

Here inserting event is handled to add TaskID field to values based on selected value of TaskID’s DropDownlist.

Wednesday, April 01, 2009

Getting default browser’s path

Following registry keys hold default browser’s application path

1. HKEY_CLASSES_ROOT\http\shell\open\command

2. HKEY_LOCAL_MACHINE\SOFTWARE\Classes\http\shell\open\command

As expected there is no consistency here. We tested following browsers

  1. Microsoft Internet Explorer 8.0.6001.18702
  2. Mozilla Firefox 3.0.7
  3. Google Chrome 1.0.154.53
  4. Opera 9.63
  5. Apple Safari 3.2.1 (525.27.1)

First options works for all browsers except Safari. Second option is not very much recommended. Following code snippet extracts browser path from open command.

using System.Text.RegularExpressions;
using Microsoft.Win32;
RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(@"\http\shell\open\command");
string[] valnames = regKey.GetValueNames();
string val0 = (string)regKey.GetValue(valnames[0]);
Regex regex = new Regex("[\\w\\W\\d]*.exe\"",RegexOptions.IgnoreCase);
Match match = regex.Match(val0);
MessageBox.Show(match.Value);

Monday, February 02, 2009

Parsing comma separated files (csv) in C#

Parsing a comma separated file. This task sounded so simple for this till the time I received couple of bugs.

Initially I attempted with a simple approach as shown below.

        using (StreamReader csvFile = new StreamReader(filePath, Encoding.Default))
{
//First line must contain columns
string csvHeader = csvFile.ReadLine();

//Comma seperated values
csvColumns.InsertRange(0, csvHeader.Split(','));
}

Due to these bugs I educated myself about rules of CSV. I can quote couple of references here.

Wiki Comma-separated values and CSV standard.

Important point to note here is that each value in CSV can contain a comma or newline or quotes embedded in itself.

This simple point changes rules of games very much. Normal stream operations to read line are of no use here. As well split functions are of no use. So only option left out is to parse byte by byte watching for characters to skip and add.

Here is the code using which I managed to parse a Csv and resolved bugs. It is too primitive but works.

namespace CsvUtilities
{
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Globalization;

public sealed class CsvParser
{
//constants
private const int quote = '"';
private const int comma = ',';
private const int carrierreturn = '\r';
private const int linefeed = '\n';

//File Name
private string fileName;

/// <summary>
/// File name propery
/// </summary>
public string FileName
{
get { return fileName; }
set { fileName = value; }
}

//shared reader
FileStream reader;

//Flag to signal end of line
private bool endofline;

#if DEBUG
public TimeSpan timeSpan;
#endif

/// <summary>
/// Default parameter less constructor
/// </summary>
public CsvParser()
{

}

/// <summary>
/// Constructor to set file
/// </summary>
/// <param name="fileName">File name to parse</param>
public CsvParser(string fileName)
{
//Input validation
if (String.IsNullOrEmpty(fileName))
throw new ArgumentException("File name can not be null");
if (File.Exists(fileName) == false)
throw new FileNotFoundException(fileName);

this.fileName = fileName;
}

/// <summary>
/// Parses Csv and return a data table
/// </summary>
/// <param name="headerIncluded">If header is not included colums will be named Column(x)</param>
/// <returns>Data table with rows populated from Csv file</returns>
public DataTable Parse(bool headerIncluded)
{
DataTable dataTable = new DataTable();
dataTable.Locale = CultureInfo.InvariantCulture;
DataRow dataRow;

//Input validation
if (String.IsNullOrEmpty(fileName))
throw new ArgumentException("File name can not be null");

#if DEBUG
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
#endif
using (reader = new FileStream(fileName, FileMode.Open))
{
string value;
int idx = 0;

//Header handling
while (reader.Position != reader.Length)
{
value = GetValue();
if (headerIncluded == false)
{
value = "Column" + idx++;
if (endofline)
reader.Position = 0;
}

try
{
dataTable.Columns.Add(value);
}
catch (DuplicateNameException dnex)
{
throw;
}

if (endofline) break;
}

//Initialization
dataRow = dataTable.NewRow();
idx = 0;
endofline = false;

//Row handling
while (reader.Position != reader.Length)
{
value = GetValue();
dataRow[idx++] = value;

if (endofline)
{
dataTable.Rows.Add(dataRow);
dataRow = dataTable.NewRow();
idx = 0;
endofline = false;
}
}

}
#if DEBUG
stopwatch.Stop();
timeSpan = stopwatch.Elapsed;
#endif
return dataTable;
}

private string GetValue()
{
char currentByte; // Current Byte
char nextByte; // Next Byte

Boolean withinQuote = false; // Is current position within a quote

List<char> bytes = new List<char>();

long position = 0;

//If stream is null throw exception
if (reader == null)
throw new ArgumentException("CSVDataset: stream can not be null");

if (reader.CanRead == false)
throw new ArgumentException("CSVDataset: Can not read stream");

while (reader.CanRead)
{
currentByte = (char)reader.ReadByte();

position = reader.Position;

//If at last position terminate
if (position == reader.Length)
break;

//peek next character
nextByte = (char)reader.ReadByte();
//As ReadByte moved cursor ahead bring cursor back
reader.Seek(position, SeekOrigin.Begin);

//Current character is within the quote
if (withinQuote)
{
//Is this character a terminating quote
if ((currentByte == quote) && (nextByte == comma))
{
reader.Seek(position + 1, SeekOrigin.Begin); //jump comma
break;
}
if ((currentByte == quote) && (nextByte == quote))
{
continue;
}
else
{
bytes.Add(currentByte);
continue;
}
}

if (currentByte == quote)
{
withinQuote = true;
continue;
}
if (currentByte == comma) break;

if ((currentByte == carrierreturn) (currentByte == linefeed))
{
if ((nextByte == carrierreturn) (nextByte == linefeed))
{
reader.Seek(position + 1, SeekOrigin.Begin); //jump CR+LF
}
endofline = true;
break;
}

bytes.Add(currentByte);
}

//Reading value completed. Return
return new string(bytes.ToArray());
}
}
}

Hope this is useful to start with. Advanced parsers can be found at codeproject http://www.codeproject.com/KB/database/CsvReader.aspx

Friday, April 11, 2008

How to access explicit interface methods from another method

Explicit interface methods are prefered to instance members for following reasons

a) They are accessible only through interface

b) They support multiple levels of inheritance chain

Some insight. Take this example.

a) Take simple console application

b) Add an interface

c) Implement interface

d) Create Object of the class and try to access interface method

e) Cast it with interface and access

f) Call another explicit method method

g) Call another explicit methos by casting this object with interface

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassMonitorLibrary
{

public class Program
{
//Entry point
public static void Main(String [] args)
{
#region Not accessible directly
//Object is accessible
//IFile im = (IFile)(new InterfaceMethods());
#endregion
InterfaceMethods im = new InterfaceMethods();
im.GetFile("Data.txt", 10);
}
}

//Simple interface
interface IFile
{
bool GetFile(string fileName, int length);
bool IsFileExists(string fileName);
}

//Interface implementation
class InterfaceMethods : IFile
{
bool IFile.GetFile(string fileName, int length)
{
#region how to access method
//if (((IFile)this).IsFileExists(fileName))
#endregion
if
(IsFileExists(fileName))
Console.WriteLine("FileExists");

return true;
}

bool IFile.IsFileExists(string fileName)
{
return true;
}
}
}

Tuesday, July 31, 2007

Split letters and numbers

using System;
using System.Text;
using System.Text.RegularExpressions;

namespace Program
{
    public class App
    {
        static void Main(string [] args)
        {
            string strtemp ="AB324hgdf89dfg";
            string strpart;
            Nullable<int> npart;
            SplitLettersAndNumbers(strtemp,out strpart,out npart);
            Console.WriteLine("{0} : {1} - {2}",strtemp,strpart,npart);
        }

        /// <summary>
        /// This method extracts all numerals and alphabets from a given string
        /// </summary>
        /// <param name="instr">String input</param>
        /// <param name="strpart">all alphabets as string</param>
        /// <param name="intpart">all numerals as string</param>
        /// <returns>return if success else false<returns>
        public static bool SplitLettersAndNumbers(string instr, out string strpart, out Nullable<int> intpart)
        {

            string strtemp = null; //buffer to hold letters
            string nstrtemp = null;//buffer to hold numbers

            if (instr == null) // invalid option
            {
                strpart = null;
                intpart = null;
                return false;
            }

            string[] m1 = Regex.Split(instr, @"\d");//All letters
            string[] m2 = Regex.Split(instr, @"\D");//All numbers

            //Concatenate all strings
            StringBuilder sb = new StringBuilder(instr.Length);
            foreach (string si in m1)
            {
                //Do extra processing if needed
                sb.Append(si);
            }
            strtemp = sb.ToString();

            //Concatenate all Numbers.
            foreach (string si in m2)
            {
                //Do extra processing if needed
                nstrtemp += si;
            }

            //Update out parameter for letters
            if (strtemp != "")
            {
                strpart = strtemp;
            }
            else
            {
                strpart = null;
            }

            //Update out parameter for numbers
            if (nstrtemp != "")
            {
                intpart = int.Parse(nstrtemp);
            }
            else
            {
                intpart = null;
            }

            return true;
        }
    }
}