C# - Monitoring folder and files

If you want to get a notification whenever a folder or any files is changed, .Net Framework provides a class name FileSystemWatcher to ease your coding. It provides an event for any files that is modified, created or deleted.

FileSystemWatcher fileWatcher = new FileSystemWatcher();
fileWatcher.Path = "C:\Data";
fileWatcher.Filter = "*.txt";
fileWatcher.IncludeSubdirectories = false;
fileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
fileWatcher.Changed += new FileSystemEventHandler(OnFileChanged);

The 'Filter' property is used to set what type of file being monitor. If you want to monitor all file types, just change it to "*.*" or you can specify other file type like "*.jpeg", "*.wmv" or others. The 'IncludeSubdirectories' as the name suggested is set to either include the sub directory in FileSystemWatcher monitoring or ignore it. The 'NotifyFilter' is used with Changed event, when the file attribute like last write or file name is change, the Changed event will be invoke. There is also some other event for this class as shown below:

// When a file is created in the folder
fileWatcher.Created += new FileSystemEventHandler(OnFileModified);
// When a file is deleted from the folder
fileWatcher.Deleted += new FileSystemEventHandler(OnFileModified);
// When a file in the folder is renamed
fileWatcher.Renamed += new FileSystemEventHandler(OnFileModified);

fileWatcher.EnableRaisingEvents = true;

private void OnFileModified(object sender, FileSystemEventArgs e)
{
    if (e.ChangeType == WatcherChangeTypes.Created || e.ChangeType == WatcherChangeTypes.Deleted)
    {
        ....
    }
}


You must set the 'EnableRaisingEvents' as true to start the FileSystemWatcher.

Read more...

C# - Simple SQL command

Here are some simple code in C# if you want to select data from your database.
Product
IdProductNameDescription


DataTable dataTable = new DataTable();
string connStr = "Data Source=MachineName\SQLEXPRESS;Initial Catalog=DatabaseName;Integrated Security=True";
string query = "select Id, ProductName, Description from Product";
using (SqlConnection conn = new SqlConnection(connStr))
{
    SqlDataAdapter da = new SqlDataAdapter(query, conn);
    da.Fill(dataTable);
}

foreach (DataRow row in dataTable.Rows)
{
    Console.WriteLine(row["Id"].ToString(), row["ProductName"].ToString(), row["Description"].ToString());
    ....
}

Data Source is the name of the database server. Initial Catalog is the database name. If you set the Integrated Security to true, it will used the Windows account of the current process to login to the server. In case the user id and password is different from the windows account, use this

string connStr = "Data Source=MachineName\SQLEXPRESS;Initial Catalog=DatabaseName;User ID=username;Password=yourPassword";



You can also use SqlCommand to read data from the database. For other SQL command like insert, delete and update, I'm not sure if there is other way beside using SqlCommand.

using (SqlConnection conn = new SqlConnection(connStr))
{
    SqlCommand dataCommand = new SqlCommand();
    dataCommand.Connection = conn;
    dataCommand.CommandText = "update Product set ProductName='NewProductName' where Id='30'";

    conn.Open();
    int x = dataCommand.ExecuteNonQuery();
    conn.Close();
}

Read more...

Google Wave invite

If you are looking for a Google Wave invite, just leave a thank you and your e-mail. I will sent it to you. Current invitation left 13 and after it is send, the invitation might take 1 or 2 days to reach you.


Read more...
There is a time where you need to implement a task on another thread to prevent freezing your UI, update your UI when the task is done. For that, you can use BackgroundWorker that is provided in the .Net Framework.

BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(BgwDoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BgwRunWorkerCompleted);

DoWork event is invoked when this backgroundworker is called while RunWorkerCompleted is invoked when backgroundworker completed the task. All long running and intensive task is implemented in the BgwDoWork function and BgwRunWorkerCompleted function is used to update the main thread or UI. When you wan to start the thread, just called the RunWorkerAsync.

bgw.RunWorkerAsync(); // or
bgw.RunWorkerAsysnc(someobject); //if you need to pass parameter

private void BgwDoWork(object sender, DoWorkEventArgs e)
{
     SomeObject test = e.parameter as SomeObject;
     ......
     // perform some task
     ......
     e.Result = result;
}

private void BgwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     SomeObject2 test2 = e.Result as SomeObject2;
     .....
     // Update main thread or UI
}


e.Result in BgwDoWork is used to pass object between backgroundworker thread to main thread. If you pass a parameter when calling the RunWorkerAsync, you can get this with e.parameter. You can also report the progress of your running task but you need to set WorkerReportsProgress to true when you declare the backgroundworker variable.

bgw.WorkerReportsProgress = true;
bgw.ProgressChanged += new ProgressChangedEventHandler(BgwProgressChanged);

private void BgwDoWork(object sender, DoWorkEventArgs e)
{
     BackgroundWorker bgWorker = (BackgroundWorker)sender;
     ......
     // perform some task
     bgWorker.ReportProgress(someobject);
     ......
}

private void BgwProgressChanged(object sender, ProgressChangedEventArgs e)
{
     // update progress bar or any UI
}

Read more...

Differences between function and stored procedure in SQL

Before you decide in using function or stored procedure, you must know that a function cannot used SQL statement like INSERT, UPDATE and DELETE while a stored procedure can. A function also does not support error handling but a stored procedure support error handling (you must include the error handling). Below are more on differences between both:
  1. Function can be used in a select statement but a stored procedure can't.
  2. Functions are mostly used for computations while Stored Procedures are used for business logic.
  3. Function must return a value while Stored Procedure are optional.
  4. Function accept only input parameters while Stored Procedures can accept input and output parameters.
  5. GETDATE() or other non-deterministic functions is not allow in Function but are allow in Stored Procedures.
  6. StoredProcedure can use Temporary Tables while Function can't.
  7. Function can not Execute Dynamic SQL while a Stored Procedure can.

Read more...

WPF - Resources

When you create a WPF application, there is a time when you need to add resources to your application such as image, text file, xml file and etc. When you specify the source for this resources, you can either point it to the absolute path or relative path. Absolute path is the exact location while relative path is the location depending on your current working directory.

For example,

Current working directory - C:\Projects\MyApplication
Absolute path - C:\Projects\MyApplication\Resources
Relative path - .\Resources
Absolute path - C:\Projects\MyApplication2\Resources
Relative path - ..\MyApplication2\Resources

When your application is using a resource, you can either point it to the path or embed the resource inside your application. For example, you wan to show an image in your application with directly pointing to the sources

<image Source="C:\Projects\MyApplication\Resources\blank.jpeg">

or embedding the image inside your application

<image Source="/MyApplication;component/blank.jpeg">

Source format: "/project name;component/image-relative-path"

Note: To embed the image, in solution explorer, right click on the project node and click add existing item, browse to the image you want and add. Right click on this image file and select property, make sure the build action is set to resource.

The image can also be added to the properties.resources at the solution explorer, but you will need to convert it to BitmapImage as the image is saved as Bitmap. You can also add string as normal variable and others file type to properties.resources. To access it later in c# code-behind, you just call


string str = Properties.Resources.string-name-you-put;
Bitmap bmp = Properties.Resources.bitmap-name-you-put;


Read more...

WPF - Splash screen with status update

When your WPF application start up, there are times when it need to load some data or doing some long running task before your application window is fully loaded. So, splash screen is added to make it feel more responsive, but it is still not enough, some application may take a few task to run before loading the window. Most user will feel the application is hanging on splash screen and won't loads. So i thought adding a status update to the splash screen. Each completed task will update this status label.

This splash screen is actually a window control with windowstyle set to none and other properties set. You can add your splash image inside and set splash screen resolution to be the same with the image resolution. I posted the solution here.

To show the splash screen, you need to fire the event on startup. Then call Splash.BeginDisplay();.


App.xaml
<Application x:Class="SplashScreenWithStatus.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml" Startup="Application_Startup">
    <Application.Resources>
    </Application.Resources>
</Application>


App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
    Splash.BeginDisplay();
}


Then you need to call Splash.EndDisplay(); after you application's main window is loaded. I added Thread.Sleep(..); to simulate a long running task and update the status label accordingly when initializing component.


Read more...
<Peoples>
    <People>
        <Name Age="26" Gender="M">John</Name>
        <Status>Single</Status>
        <Occupation>Accountant</Occupation>
    </People>
    <People>
        <Name Age="31" Gender="M">David</Name>
        <Status>Married</Status>
        <Occupation>Engineer</Occupation>
        <Children>
            <Name Gender="M">Ryan</Name>
            <Name Age="5" Gender="F">Peggy</Name>
        </Children>
    </People>
</Peoples>


Root /Peoples
Name/Peoples/People/Name or //People/Name
(John, David)
//Name or //*[name()='Name']
(John, David, Ryan, Peggy)
//People/Children/Name or //Children/Name
(Ryan, Peggy)
Status/Peoples/People/Status
or //Status
or //*[name()='Status']
(Single, Married)
Descendent of people//People/descendant::*
(John
Single
Accountant

David
Married
Engineer
Ryan
Peggy)
All Element/*
Name with 3 ancestor/*/*/*/Name (Ryan, Peggy)
Name with 2 ancestor/*/*/Name (John, David)
First //People/Status//People/Status[1] (Single)
First //Children/Name//People/Children/Name[1] (Ryan)
Second //People/Name//People/Name[2] (David)
Last //People/Status//People/Status[last()] (Married)
Age attribute//@Age (26,31,5)
//Name[@Age] (John, David, Peggy)
//Name[@Age='31'] (David)
//Name[@Gender='M'] (John,David)
All attribute//@* (26 M,31 M,M,5 F)
No Age attribute//Name[not(@Age)] (Ryan)
Element with 3 descendent//*[count(*)=3]
<People>
    <Name Age="26" Gender="M">John</Name>
    <Status>Single</Status>
    <Occupation>Accountant</Occupation>
</People>
Name and Status//Name | //Status
(John Single, David Married, Ryan, Peggy)
Select ancestors//Children/ancestor::*
People & Peoples
Following sibling//Name/following-sibling::*
Status & Occupation & Children
(Single Accountant,Married Engineer Ryan Peggy)
Preceding sibling//Occupation/preceding-sibling::*
Name & Status
(John Single, David Married)


Read more...

WPF - BitmapImage

Converting Bitmap to BitmapImage.
code
Bitmap bmp = GetBitmap(); // Get bitmap from somewhere
BitmapImage bi = new BitmapImage();
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
bi.BeginInit();
ms.Seek(0, SeekOrigin.Begin);

bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms;
bi.DecodePixelHeight = 30;
bi.DecodePixelWidth = 50;
bi.EndInit();
bi.StreamSource.Dispose();

// Dispose and free resources.
bmp.Dispose();
bmp = null;
ms.Dispose();
ms = null;


Converting Byte[] to BitmapImage.
code
Byte[] imageByte = GetImageByte(); // Get byte[] from somewhere
MemoryStream ms = new MemoryStream(imageByte);
ms.Seek(0, SeekOrigin.Begin);

BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();

ms.Dispose();
ms = null;


Saving BitmapImage as jpeg file.
code
BitmapImage bi = GetBitmapImage() // Get bitmapimage from somewhere
using (FileStream stream = new FileStream("img.jpeg", FileMode.Create))
{
    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(bi));
    encoder.Save(stream);
    stream.Close();
}


Converting BitmapImage to Byte[].
code
BitmapImage bi = GetBitmapImage() // Get bitmapimage from somewhere
Stream stream = bi.StreamSource;
Byte[] imageByte = null;
using (BinaryReader reader = new BinaryReader(stream))
{
    imageByte = reader.ReadBytes((Int32)stream.Length);
}


Converting BitmapImage to Bitmap. (Seldom use)
code
BitmapImage bi = GetBitmapImage(); // Get bitmapimage from somewhere
MemoryStream ms = newMemoryStream();
BitmapEncoder encoder = new BitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bi));
encoder.Save(ms);
Bitmap bmp = new Bitmap(ms);

Read more...
top