Hash

Entries tagged as ‘CodeProject’

Binding a List with DataGridView

March 31, 2009 · 2 Comments

DataGridView control for WinForms was introduced in .NET 2.0 and VS 2005. Its a pretty flexible control offering a lot more than DataGrid control in the previous version. Recently I was looking for a control which inherently support embedded control in its cells and DataGridView came up as a strong candidate. It has a native support of some basic embedded controls like TextBox, CheckBox etc. I explored it a little more and found it extremely easy and quick to program. My usage of this control is not much advanced which I describe here.

It has been built for displaying relational data so you can bind it to a DataTable from the database or an array of business objects. What I have done here is that I used a BindingList object which is also provided with .NET and is a useful variant of List object. The advantage of BindingList is that it can act as a sink of events while simple List object can’t.  It provides a PropertyChangedEventHandler which is called when a row is added/updated or deleted. So you simple bind this list to your DataGridView and both objects will remain synchronized. If you add/delete/update something to one the other object will simple pick it up from the event. Have a look at this:

private void MyForm_Load(object sender, EventArgs e)
{
             FillUpDataGridView();
             MyDataGridView.DataSource = Settings.MyBindingList;
}

The method FullUpDataGridView reads some business objects from a data source into the BindList object and the next statement displays the data in the control. You also need to bind DataGridView columns to properties of these business objects to specify which properties are displayed and which are not and their respective order.

Binding properties with columns of DataGridView control

This image shows name of the propery FeedEnabled which has been bound with the column "Enabled". My business object looks like:

public class FeedViewRow : INotifyPropertyChanged
{
    private string _FeedUri;
    private bool _AutoUpdate;
    private bool _FeedEnabled;         // Parameterless constructor for serialization
    public FeedViewRow() {  }
    public FeedViewRow(string Uri, bool Auto, bool Enabled)
    {
        _FeedUri = Uri;
        _AutoUpdate = Auto;
        _FeedEnabled = Enabled;
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public bool FeedEnabled
    {
        get { return _FeedEnabled; }
        set { _FeedEnabled = value; this.NotifyPropertyChanged("FeedEnabled"); }
    }
    public string FeedUri
    {
        get { return _FeedUri; }
        set { _FeedUri = value; this.NotifyPropertyChanged("FeedUri"); }
    }
    public bool AutoUpdate
    {
        get { return _AutoUpdate; }
        set { _AutoUpdate = value; this.NotifyPropertyChanged("AutoUpdate"); }
    }
    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

Keep a string property for TextBox and bool for CheckBox.  You object should implement the INotifyPropertyChanged interface.

After this you can simply [de]serialize the BindingList object. For serialization:

IsolatedStorageFile Storage = IsolatedStorageFile.GetUserStoreForAssembly();
IsolatedStorageFileStream File = new IsolatedStorageFileStream(StorageFileName,
FileMode.Create, FileAccess.Write, FileShare.None, Storage);
XmlSerializer Serializer = new XmlSerializer(typeof(BindingList));
Serializer.Serialize(File, this);
File.Close();
Storage.Close();

This will write out an XML of the whole list. Simple!

 

Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Categories: .NET
Tagged: , , , , , , , , , , , ,

Using the Oracle DBMS_LOCK Package

March 31, 2009 · Leave a Comment

As a standard DBMS practice Oracle provides all sort of row level and table level locking mechanism for data integrity. This built-in locking mechanism is strongly coupled with database transactions e.g. a lock acquired through the LOCK command is released automatically at the end of the transaction. Sometimes you need explicit locking with full control and independent of the transactions. This feature is provided by DBMS_LOCK.

The other day I was stuck in a legacy system where I had to provide a locking mechanism on call to a stored procedure at the database level. The procedure is called from a web farm consisting of a number of web servers and I wanted to make sure that only one web servers accesses the procedure at any given time. Although I hated such a procedure in my database but that looked like the only solution to the problem without changing some fundamentals. The DBMS_LOCK package came for my rescue and here is what I learnt from it.

This package is available to the SYS user only (may be because of its significance and impact). So if you try to access it from another user you will get an error “IDENTIFIER MUST BE DECLARED”. The solution is to write  functions on top of the DBMS_LOCK package and grant access to those functions. The DBA can thus regulate which operations are allowed to the user and which are forbidden.

CREATE OR REPLACE PROCEDURE xmode_lock_procedure (lockhandle varchar2, v_result OUT number) IS
v_lock varchar2(200);
begin
dbms_lock.allocate_unique(lockhandle, v_lock);
v_result := dbms_lock.request(v_lock, dbms_lock.x_mode);
end;

Grant access on this procedure to the user:

GRANT ACCESS ON xmode_lock_procedure TO user1;

Granting access to public is never recommended due to sensitivity of this procedure.

Similarly a procedure which releases this lock can be written as:

CREATE OR REPLACE PROCEDURE lock_release (lockhandle varchar2, v_result OUT number) IS
v_lock varchar2(200);
begin
dbms_lock.allocate_unique(lockhandle, v_lock);
v_result := dbms_lock.release (v_lock);
end;

This will release the lock and in the meantime if another users requests a lock he will be blocked until this users releases the same lock. Note that the lock uniqueness is decided by the LOCKHANDLE parameter passed to the procedures.

The result returned by these procedures can be:

1: Timeout occurred
2. Deadlock occurred
3. Parameter Error
4. Already owned
5. Illegal lock handle

 

 

 


Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Categories: Oracle · TechFactor
Tagged: , , , , , , ,

C# Winforms: Using a progress bar with Web Browser Control

March 31, 2009 · 2 Comments

The .NET web browser provides a number of different events including some which tells when the browser started navigating to a web page and when that navigation completed.

These events are:

private System.Windows.Forms.WebBrowser ItemBrowser;

 

this.ItemBrowser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.ItemBrowser_Navigating);
this.ItemBrowser.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.ItemBrowser_DocumentCompleted);
this.ItemBrowser.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.ItemBrowser_Navigated);

 

This shows the functions are being called at proper events. Now let us come to the code in those functions. The goal is to show a marquee in the status bar when a page is clicked and stop that marquee when navigation is fully complete.

private void ItemBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    BrowserLabel.Text = "Loading ... ";
    BrowserProgressBar.MarqueeAnimationSpeed = 80;
    BrowserProgressBar.Style = ProgressBarStyle.Marquee;
}

 

I have created two items in the status strip. A Label named BrowserLabel and a progress bar item named BrowserProgressBar. The text property of BrowserLabel is set to “Loading … “ when a hyperlink is created. And to start the marquee we set the style of progress bar to Marquee and its speed to 80. Note that as you increase the AnimationSpeed it will slow down. It will be fastest at 1 and slowest at 100 (I have set 100 as MaxSpeed, you can change that property as well).

Now we need to stop this animation when browsing is complete:

void ItemBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    BrowserProgressBar.MarqueeAnimationSpeed = 0;
    BrowserProgressBar.Style = ProgressBarStyle.Blocks;

    BrowserLabel.Text = "Ready";
}

 

I set the style back to Block and AnimationSpeed to “0”. Style is a property and it can start/stop the animation according to its value so you don’t need to call a “start” function as required in the previous versions. Also the value of Label is reset here.

One function is still remaining:

void ItemBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    if (!ItemBrowser.IsBusy)
    {
        BrowserProgressBar.MarqueeAnimationSpeed = 0;
        BrowserProgressBar.Style = ProgressBarStyle.Blocks;

        BrowserLabel.Text = "Ready";
    }
}

 

This function is also called when navigation is completed. Although in most cases the DocumentCompleted function is sufficient but bookmark links do not call that function so Navigated function will do in those cases.

 

Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Categories: .NET · CodeProject
Tagged: , , , , , , , , , ,

C# Winforms: Create a Single Instance Form Using Singleton

March 31, 2009 · 8 Comments

A common practice in WinForms programming is to keep only one instance of a certain form in the application. A new instance of that form is never created and shown. I have previously written a small note on this topic and gave a solution here which I personally don’t like.

In this post I am presenting a much better solution which is based on the singleton pattern. Rather than each time looking for the form in a list of opened forms I make the constructor private.

Let us start with the Form:

public sealed partial class ThirdForm : Form
{

}

The class is sealed so it cannot be inherited. We don’t want a child create an instance of this class multiple times.

Now add these members and methods to the class:

private static readonly ThirdForm MyInstance = new ThirdForm();

This is the sole instance of this form. And the private constructor to avoid multiple instances outside the class:

private ThirdForm()
{
    InitializeComponent();
}

And the property to publish the sole instance:

public static ThirdForm OnlyInstance
{
    get { return MyInstance; }
}

Another functionality that you might want to add to your Form is a new Show method. And you may also want to know whether the form was already opened or your opened it. Here is the answer to these questions. Add this code to your form class to Show() or Select() if already shown.

public new void Show()
{
    if (IsShown)
        base.Show();
    else
    {
        base.Show();
        IsShown = true;
    }
}

A variable IsShown of type bool is added to the form to record the current state.

private static bool IsShown = false;

static ThirdForm()
{
    OnlyInstance.FormClosing += new FormClosingEventHandler(OnlyInstance_FormClosing);
}

private static void OnlyInstance_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = true;
    IsShown = false;

    OnlyInstance.Hide();
}

The variable IsShown is set to false when the only instance of this form is closed. But remember its a singleton. We can’t let the only instance die so we catch FormClosing event and Hide() the form instead of closing it.

This solution looks elegant than looking for an opened form in an array but it has draw backs. You cannot catch the FormClosed event because it will never happen. The form is created only once so if your form is based on some volatile objects you will never see the change even if you close and open it again. May be I try to address these problems in another post some day. Spot On!

Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Categories: .NET
Tagged: , , , , , , , , ,

Creating one-to-many relationship in NHibernate

March 31, 2009 · 9 Comments

We have recently brought in NHibernate in our environment and I was the first one in the team to do something real with it. It was going perfect until this one-to-many relationship and then I had to consult the architect in UK to get it going :( Infact I successfully implemented many-to-many but could not do one-to-many . *&#%&*#W(*(*&%#

Anyways, we had a class SearchCritera having a list of SearchCriterion. The mapping file looked like:

<class name="BusinessObjects.Search.SearchDocumentCriteria" table="searchdocumentcriteria">
<id name="Id" column="id">
<generator class="sequence">
<param name="sequence">pc_searchdocumentcriteria</param>
</generator>
</id>
<bag name="Criteria" lazy="false" cascade="all" inverse="true">
<key column="criteriaid"/>
<one-to-many class="BusinessObjects.Search.SearchDocumentCriterion"/>
</bag>
</class>
<class name="BusinessObjects.Search.SearchDocumentCriterion" table="searchdocumentcriterion">
<id name="Id" column="id">
<generator class="sequence">
<param name="sequence">pc_searchdocumentcriterion</param>
</generator>
</id>
<property name="FieldName" column="fieldname" type="string"/>
<many-to-one name="Id" class="BusinessObjects.Search.SearchDocumentCriteria" column="criteriaid" not-null="true"/>
<bag name="Expression" lazy="false" cascade="all" inverse="true">
<key column="criterionid"/>
<one-to-many class="Search.SearchDocumentCriterionOperatorValue"/>
</bag>
</class>

Look at the red line, it maps back to the parent class’s column Id. This is what I found in the manual and an example on the internet as well. But we were getting the error:

Unknown entity class: System.Int32

Later we found that we need to have a parent reference in the child class as well which make the relationship 2-way. So we added the following property in the SearchDocumentCriterion class:

public virtual SearchDocumentCriteria Parent { get; set; }

And the following change in the mapping file:

<many-to-one name="Parent" class="BusinessObjects.Search.SearchDocumentCriteria" column="criteriaid" not-null="true"/>

Note the Parent property instead of Id property. This solved the problem :D Anyone having a better solution for one-to-many relationship in NHibernate? Yes, I don’t like the two-way relationship.

 

 


Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Categories: .NET · CodeProject
Tagged: , , , , , , ,

C#: Parsing DateTime with TimeZone

February 2, 2009 · 4 Comments

I was writing code to parse the RSS Feed XML files the other day and I was getting exceptions on the published date.  The was happening because of the special format which is not supported by .NET. The published dates had the format:

Mon, 02 February 2009, 16:52:10 AEST

The names of the time zones are not supported by .NET because they are not unique. Different time zones in the world can have the same abbreviation.

If you try to parse this string using Convert.ToDateTime method the following error is shown:

System.FormatException: The string was not recognized as a valid DateTime. There is an unknown word starting at index XYZ.

 

To handle this situation I have written this piece of code as a separate class called Utils. The array is a private member of the class.

private static string[][] TimeZones = new string[][] {
    new string[] {"ACDT", "+1030", "Australian Central Daylight"},
    new string[] {"ACST", "+0930", "Australian Central Standard"},
    new string[] {"ADT", "-0300", "(US) Atlantic Daylight"},
    new string[] {"AEDT", "+1100", "Australian East Daylight"},
    new string[] {"AEST", "+1000", "Australian East Standard"},
    new string[] {"AHDT", "-0900", ""},
    new string[] {"AHST", "-1000", ""},
    new string[] {"AST", "-0400", "(US) Atlantic Standard"},
    new string[] {"AT", "-0200", "Azores"},
    new string[] {"AWDT", "+0900", "Australian West Daylight"},
    new string[] {"AWST", "+0800", "Australian West Standard"},
    new string[] {"BAT", "+0300", "Bhagdad"},
    new string[] {"BDST", "+0200", "British Double Summer"},
    new string[] {"BET", "-1100", "Bering Standard"},
    new string[] {"BST", "-0300", "Brazil Standard"},
    new string[] {"BT", "+0300", "Baghdad"},
    new string[] {"BZT2", "-0300", "Brazil Zone 2"},
    new string[] {"CADT", "+1030", "Central Australian Daylight"},
    new string[] {"CAST", "+0930", "Central Australian Standard"},
    new string[] {"CAT", "-1000", "Central Alaska"},
    new string[] {"CCT", "+0800", "China Coast"},
    new string[] {"CDT", "-0500", "(US) Central Daylight"},
    new string[] {"CED", "+0200", "Central European Daylight"},
    new string[] {"CET", "+0100", "Central European"},
    new string[] {"CST", "-0600", "(US) Central Standard"},
    new string[] {"CENTRAL", "-0600", "(US) Central Standard"},
    new string[] {"EAST", "+1000", "Eastern Australian Standard"},
    new string[] {"EDT", "-0400", "(US) Eastern Daylight"},
    new string[] {"EED", "+0300", "Eastern European Daylight"},
    new string[] {"EET", "+0200", "Eastern Europe"},
    new string[] {"EEST", "+0300", "Eastern Europe Summer"},
    new string[] {"EST", "-0500", "(US) Eastern Standard"},
    new string[] {"EASTERN", "-0500", "(US) Eastern Standard"},
    new string[] {"FST", "+0200", "French Summer"},
    new string[] {"FWT", "+0100", "French Winter"},
    new string[] {"GMT", "-0000", "Greenwich Mean"},
    new string[] {"GST", "+1000", "Guam Standard"},
    new string[] {"HDT", "-0900", "Hawaii Daylight"},
    new string[] {"HST", "-1000", "Hawaii Standard"},
    new string[] {"IDLE", "+1200", "Internation Date Line East"},
    new string[] {"IDLW", "-1200", "Internation Date Line West"},
    new string[] {"IST", "+0530", "Indian Standard"},
    new string[] {"IT", "+0330", "Iran"},
    new string[] {"JST", "+0900", "Japan Standard"},
    new string[] {"JT", "+0700", "Java"},
    new string[] {"MDT", "-0600", "(US) Mountain Daylight"},
    new string[] {"MED", "+0200", "Middle European Daylight"},
    new string[] {"MET", "+0100", "Middle European"},
    new string[] {"MEST", "+0200", "Middle European Summer"},
    new string[] {"MEWT", "+0100", "Middle European Winter"},
    new string[] {"MST", "-0700", "(US) Mountain Standard"},
    new string[] {"MOUNTAIN", "-0700", "(US) Mountain Standard"},
    new string[] {"MT", "+0800", "Moluccas"},
    new string[] {"NDT", "-0230", "Newfoundland Daylight"},
    new string[] {"NFT", "-0330", "Newfoundland"},
    new string[] {"NT", "-1100", "Nome"},
    new string[] {"NST", "+0630", "North Sumatra"},
    new string[] {"NZ", "+1100", "New Zealand "},
    new string[] {"NZST", "+1200", "New Zealand Standard"},
    new string[] {"NZDT", "+1300", "New Zealand Daylight "},
    new string[] {"NZT", "+1200", "New Zealand"},
    new string[] {"PDT", "-0700", "(US) Pacific Daylight"},
    new string[] {"PST", "-0800", "(US) Pacific Standard"},
    new string[] {"PACIFIC", "-0800", "(US) Pacific Standard"},
    new string[] {"ROK", "+0900", "Republic of Korea"},
    new string[] {"SAD", "+1000", "South Australia Daylight"},
    new string[] {"SAST", "+0900", "South Australia Standard"},
    new string[] {"SAT", "+0900", "South Australia Standard"},
    new string[] {"SDT", "+1000", "South Australia Daylight"},
    new string[] {"SST", "+0200", "Swedish Summer"},
    new string[] {"SWT", "+0100", "Swedish Winter"},
    new string[] {"USZ3", "+0400", "USSR Zone 3"},
    new string[] {"USZ4", "+0500", "USSR Zone 4"},
    new string[] {"USZ5", "+0600", "USSR Zone 5"},
    new string[] {"USZ6", "+0700", "USSR Zone 6"},
    new string[] {"UT", "-0000", "Universal Coordinated"},
    new string[] {"UTC", "-0000", "Universal Coordinated"},
    new string[] {"UZ10", "+1100", "USSR Zone 10"},
    new string[] {"WAT", "-0100", "West Africa"},
    new string[] {"WET", "-0000", "West European"},
    new string[] {"WST", "+0800", "West Australian Standard"},
    new string[] {"YDT", "-0800", "Yukon Daylight"},
    new string[] {"YST", "-0900", "Yukon Standard"},
    new string[] {"ZP4", "+0400", "USSR Zone 3"},
    new string[] {"ZP5", "+0500", "USSR Zone 4"},
    new string[] {"ZP6", "+0600", "USSR Zone 5"}
};

 

Then there is a static initializer of the class which creates a Hashtable for quick search.

private static Hashtable ZoneTable;

static Utils()
{
    ZoneTable = new Hashtable(50);

    foreach(string[] TimeZone in TimeZones)
    {
        ZoneTable.Add(TimeZone[0], TimeZone[1]);
    }
}

The actual conversion method is quite simple. First, try to parse the string without any change. This step can be skipped actually because all dates from an RSS Feed XML will contain the time zone name so this might be an overhead. If the parsing fails we replace the time zone name with the the actual offset.

public static DateTime ConvertWithTimezone(string StrDate)
{
    DateTime ConvertedDate;

    try
    {
        ConvertedDate = Convert.ToDateTime(StrDate);
        // just a plain date
        return ConvertedDate;
    }
    catch (FormatException fex)
    {
        // try finding a timezone in the date
        int TZstart = StrDate.LastIndexOf(" ");

        if (TZstart != -1)
        {
            string TZstr = StrDate.Substring(TZstart+1); // +1 to avoid the space character
            string TZvalue = ZoneTable[TZstr] as string;

            // its a timezone problem ...
            if (TZvalue != null)
            {
                // replace timezone name with actual hours (AEST = +1000)
                string NewDateStr = StrDate.Replace(TZstr, TZvalue);

                try
                {
                    ConvertedDate = Convert.ToDateTime(NewDateStr);

                    // success this time
                    return ConvertedDate;
                }
                catch (FormatException innerfex)
                {
                    // something else wrong, we dont know what to do
                    throw innerfex;
                }
            }
        }

        throw fex;
    }
}

Here we are. This is just like a wrapper on Convert.ToDateTime which modifies the date string before parsing it.

And have you noticed that the array of time zones is not complete. There are other time zones as well but I am using just the famous ones. The list of date times was taken from http://bytes.com/groups/net-c/214648-how-do-i-parse-date-w-time-zone.

Categories: .NET
Tagged: , , , , , , , , , ,