Microsoft Expression Blend, WPF – ListBoxItem selection and highlighting

In this small blog I would like to demonstrate how we can use Microsoft Expression Blend 3.0 to handle mouse over event to change the background color of ListBoxItem. At the end of this post we will have something like this

ListBoxItem selection and highlighting

You can see that the list box has following properties.
– Selected: Background = Blue, Foreground = White
– Mouse-hovered: Background = ActiveBlue
– Not of cases above: Background = SkyBlue
Separating with color makes our list box more beautiful and easy to observe. So let’s open Blend and create an new WPF Application

Resize main window and add a list box on it. Then add some listboxitems so that we can see the animation. To add listboxitem, simply right click on listbox in “Objects and Timeline” windows then choose “Add ListBoxItem”.

After adding some items for testing, now we must create a style for handling mouse click, hover event and color animation. To simplify the process, instead of creating myself a completely new style, I would like to reuse the template of Blend and edit it to fulfill my purposes. Then right click on the list box, choose “Edit Additional Templates” –> “Edit Generated Item Container (ItemContainerStyle)” –> “Edit a Copy”.

On the “Create Style Resource”, enter the name of your style. I use “ListBoxItemStyleHighlighting” and press ok. Now it’s time to edit our style. Click on “Resources” Window, browse to “ListBoxItemStyleHighlighting” and press “Edit resource”

Then click on the small combo box below the title of design window and choose “Edit Template” –> “Edit Current”.

Now we will handle the behavior of listboxitem for each mouse action. Let’s consider all of our cases:
– When item is selected, the condition for Trigger should be IsSelected=true
– When item is not mouse-hovered, the condition for Trigger should be IsSelected = false and IsMouseOver = false

1. Selected
On mouse click, we would like to change background color to blue and foreground to white. Navigate to Triggers windows and edit the Trigger “IsSelected=true”

On frame “Properties when active”, click on the property which we want to edit. For example, click on Bd.Background, on the properties windows, choose the color what we want. This color will be shown as background of listboxitem when it’s selected.
2. Not mouse-hovered
Now we would like to handle the not mouse-hovered. We would like that when the mouse is not over the listboxitem, the item will have a Skyblue.  So come back to Triggers windows, edit the second trigger to “IsSelected=True and IsSelectionActive=False” to “IsSelected=False and IsMouseOver=False” and delete all existing entries in “Properties when active” window.

We have added handler to handle event when listboxitem is not selected and not mouse-hovered. Now we should tell handler what he should do. Click on “+” button beside “Actions when activating” and add new Storyboard.
Switch to XAML Code and edit our story board by adding ColorAnimation into it.

<Storyboard x:Key="Storyboard1">
	<ColorAnimation Storyboard.TargetName="Bd" Storyboard.TargetProperty="Background.Color" To="SkyBlue" AutoReverse="False" Duration="0:0:0.5"/>
</Storyboard>

3. Mouse-hovered

To handle this event, we just need to add one more Storyboard to the second trigger for the “Actions when deactivating” and add code for Storyboard

<Storyboard x:Key="Storyboard2">
 <ColorAnimation Storyboard.TargetName="Bd" Storyboard.TargetProperty="Background.Color" To="AliceBlue" AutoReverse="False" Duration="0:0:0.5"/>
</Storyboard>

You can adjust the color as you like. The complete source code you can download here “ListBoxItem selection and highlighting

C# – Serialize and deserialize data

When I wrote a small application with Client-Server model which sends data over TCP socket, I would like to build an intelligent way which serialize all of my data into stream, send this stream over socket and deserialize it back at server/client site. Using serialization all of data will be stored in stream or byte array and it is completely suitable for communicating over socket. To convert our object into stream using serialization is pretty simple. In this small example below, I would like to illustrate how we can serialize our object.

The example is a small management application which manages person with their information. To simplify the problem, we restrict the number of member only until 10 persons and manage them in a list

private const int cnstMax = 10;
private Person[] m_pList = new Person[cnstMax];
private int m_nPos = 0;

Class Person indicates and contains all of information of a member. It will be set with [Serializable] Attribute so that we can serialize it later. This attribute is a condition so that the serialize process runs smoothly later, without setting this attribute we can not serialize this type.

[Serializable]
private class Person
{
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public DateTime DateOfBirth { get; set; }
	public bool Student { get; set; }
}

Through the components in dialog we can add,edit more members in our database and the serialization comes at the end with closing dialog. We will flush all data in member list into stream and store in a file.

private void SaveToFile()
{
	FileStream fsData = new FileStream("Person.dat", FileMode.OpenOrCreate, FileAccess.Write);
	BinaryFormatter bfFormatter = new BinaryFormatter();
	for (int nIndex = 0; nIndex < cnstMax; nIndex++)
	{
		bfFormatter.Serialize(fsData, m_pList[nIndex]);
	}
	fsData.Close();
}

BinaryFormatter class serializes and deserializes an object, or an entire graph of connected objects, in binary format. Besides of this serialization there is still xml serialization but I find binary serialization is much more common. We can apply it for any case requiring serialization. To deserialize the data back, just read data from file back to stream and restore all information back with type of Person.

private void ReadFromFile()
{
	FileStream fsFile = new FileStream("Person.dat", FileMode.OpenOrCreate, FileAccess.Read);
	BinaryFormatter bfFormatter = new BinaryFormatter();
	if (fsFile.Length > 0)
	{
		for (int nIndex = 0; nIndex < cnstMax; nIndex++)
		{
			m_pList[nIndex] = (Person)bfFormatter.Deserialize(fsFile);
		}
		fsFile.Close();
	}
}

Using serialization we can save a lot of time for processing data. You can download code here “Serialize and deserialize data“.

Update on 15.02.2010

If you want to use XMLSerializer to serialize your data as example above, we can adjust some settings so that it works.
First, our serialized class must define a constructor without any parameter. That means we should add some code line for this constructor

[Serializable]
public class Person
{
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public DateTime DateOfBirth { get; set; }
	public bool Student { get; set; }
	public Person()
	{
		FirstName = "";
		LastName = "";
		DateOfBirth = DateTime.Parse("01.01.1900");
		Student = false;
	}
	public Person(string First, string Last, DateTime Date, bool Stu)
	{
		FirstName = First;
		LastName = Last;
		DateOfBirth = Date;
		Student = Stu;
	}
}

Second the accessible level of class should be changed to public. And class call XMLSerializer to serialize and deserialize data as following

private void ReadFromFile()
{
	try
	{
		FileStream fsFile = new FileStream("Person.dat", FileMode.OpenOrCreate, FileAccess.Read);
		if (fsFile.Length > 0)
		{
			XmlSerializer xmls = new XmlSerializer(typeof(Person[]));
			m_pList = (Person[])xmls.Deserialize(fsFile);
			fsFile.Close();
		}
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}

}

private void SaveToFile()
{
	try
	{
		FileStream fsData = new FileStream("Person.dat", FileMode.OpenOrCreate, FileAccess.Write);
		XmlSerializer xmls = new XmlSerializer(typeof(Person[]));
		xmls.Serialize(fsData, m_pList);
		fsData.Close();
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

C#, WPF – Fast image resize

Today I read a blog on http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx which introduces a new way to resize image with WPF. This new method does not use GDI+ (Microsoft Windows GDI+ is the portion of the Windows XP operating system or Windows Server 2003 operating system that provides two-dimensional vector graphics, imaging, and typography.) but it uses WPF library for resizing images very fast. You can read more details about this method in that blog. In the code below, I would like to summarize and explain a little how it works.
The main concept, that we will read all bytes of image, read the first frame of image and use class TransformedBitmap to create a new bitmap frame with the specific scale transform. In the code snippet below shows how the process runs. So that code below works we need to add reference to following assemblies: PresentationCore and WindowsBase.

static void Main(string[] args)
{
	string strFileName = "Marshimaro.jpg";
	string strThumbnail = "MarshimaroThumb.png";
	byte[] baSource = File.ReadAllBytes(strFileName);
	using (Stream streamPhoto = new MemoryStream(baSource))
	{
		BitmapFrame bfPhoto = ReadBitmapFrame(streamPhoto);

		int nThumbnailSize = 200, nWidth, nHeight;
		if (bfPhoto.Width > bfPhoto.Height)
		{
			nWidth = nThumbnailSize;
			nHeight = (int)(bfPhoto.Height * nThumbnailSize / bfPhoto.Width);
		}
		else
		{
			nHeight = nThumbnailSize;
			nWidth = (int)(bfPhoto.Width * nThumbnailSize / bfPhoto.Height);
		}
		BitmapFrame bfResize = FastResize(bfPhoto, nWidth, nHeight);
		byte[] baResize = ToByteArray(bfResize);

		File.WriteAllBytes(@"Thumbnails\" + Path.GetFileNameWithoutExtension(strThumbnail) + ".png", baResize);
		Console.WriteLine("Resize done!!!");
		Console.ReadLine();
	}
}

BitmapFrame represents image data returned by a decoder and accepted by encoders. You can see in the function ReadBitmapFrame how we can use BitmapDecoder to decode stream data of image and get the first bitmap frame.
The core of complete code is the class TransformedBitmap which supports only orthogonal transforms such as rotation transforms of 90° increments and scale transforms. In FastResize function, we apply ScaleTransform to resize image as following.

private static BitmapFrame FastResize(BitmapFrame bfPhoto, int nWidth, int nHeight)
{
	TransformedBitmap tbBitmap = new TransformedBitmap(bfPhoto, new ScaleTransform(nWidth / bfPhoto.Width, nHeight / bfPhoto.Height, 0, 0));
	return BitmapFrame.Create(tbBitmap);
}

private static byte[] ToByteArray(BitmapFrame bfResize)
{
	using (MemoryStream msStream = new MemoryStream())
	{
		PngBitmapEncoder pbdDecoder = new PngBitmapEncoder();
		pbdDecoder.Frames.Add(bfResize);
		pbdDecoder.Save(msStream);
		return msStream.ToArray();
	}
}

private static BitmapFrame ReadBitmapFrame(Stream streamPhoto)
{
	BitmapDecoder bdDecoder = BitmapDecoder.Create(streamPhoto, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
	return bdDecoder.Frames[0];
}

You can parse the code into class and use it everywhere. The complete code can be downloaded here “WPF Fast image resize

UPDATE 11.03.2010 : Insert (using Stream) to prevent memory leak.

C# – Notify changes with custom EventHandler

During my development I must find a way to notify about changes in properties of class during threads are running. To invoke event relevant to properties, we can use available EventHandler delegate or create our own one (you know that if we use our own, we always have flexible way to handle event). In this small example below I would like to demonstrate how we can create our own delegate.

This example creates a class PCProducer with 2 properties PCOwner and PCChip and I will use EventHandler and my custom one to catch all notifications created when I change the value of properties.

class PCProducer
{
	private string strPCChip;
	private string strPCOwner;

	public delegate void OwnerChangedEventHandler(string strNewOwner);
	public event OwnerChangedEventHandler OwnerChanged;
	public event EventHandler ChipChanged;

	public string PCOwner
	{
		get { return strPCOwner; }
		set
		{
			strPCOwner = value;
			if (OwnerChanged != null)
			{
				OwnerChanged(value);
			}
		}

	}

	public string PCChip
	{
		get { return strPCChip; }
		set {
			strPCChip = value;
			if (ChipChanged != null) ChipChanged(this, new EventArgs());
		}
	}
}

As you can see in the code snippet above I use both EventHandler and my custom one to release events. EventHandler delegate represents the method that will handle an event that has no event data. The standard signature of an event handler delegate defines a method that does not return a value, whose first parameter is of type Object and refers to the instance that raises the event, and whose second parameter is derived from type EventArgs and holds the event data. If the event does not generate event data, the second parameter is simply an instance of EventArgs. Otherwise, the second parameter is a custom type derived from EventArgs and supplies any fields or properties needed to hold the event data. Meanwhile my delegate takes only one argument and take no parameter as type of Object. We can of course expand the delegate to receive first parameter as type of PCProducer. We are completely free to expand our delegate. We can pass arguments as the way we like and the released event can be caught as following

 private void btnInvoke_Click(object sender, EventArgs e)
{
	Thread thCar = new Thread(StartMyThread);
	thCar.Start();
}

private void StartMyThread()
{
	PCProducer carMercedes = new PCProducer();

	carMercedes.OwnerChanged += new PCProducer.OwnerChangedEventHandler(carMercedes_OwnerChanged);
	carMercedes.PCOwner = "rongchaua";

	carMercedes.ChipChanged += new EventHandler(carMercedes_ChipChanged);
	carMercedes.PCChip = "Intel";
}

void carMercedes_ChipChanged(object sender, EventArgs e)
{
	MessageBox.Show("Chip changed");
}

void carMercedes_OwnerChanged(string strNewOwner)
{
	MessageBox.Show("Owner changed");
}

The complete source code you can download here “Notify changes with custom EventHandler

Update 15.02.2010
We can use custom EventHandler to update our GUI from other class. To do so, we just declare an event in class and handle this event in form and update component in form as following
– Define event in class

class OtherClass
{
	public delegate void UpdateLabelDelegate(string strMessage);
	public event UpdateLabelDelegate UpdateLabel;


	public void MemberFunction()
	{
		UpdateLabel("This is text from other class");
	}
}

– Handle event in form

private void Window_Loaded(object sender, RoutedEventArgs e)
{
	OtherClass ocClass = new OtherClass();
	ocClass.UpdateLabel += new OtherClass.UpdateLabelDelegate(ocClass_UpdateLabel);
	ocClass.MemberFunction();
}

void ocClass_UpdateLabel(string strMessage)
{
	lblMessage.Content = strMessage;
}

The complete source code you can download here “Access GUI from other class”