C# – WPF MVVM DataBinding 2014

It’s already 6 years since my first post about MVVM and data bindings in WPF MVVM – ListView SelectedItem and DataBinding. The MVVM pattern is now quite popular and comes into use in many WPF applications. However a lot of things have changed since 2008. We have now many new platforms where we can also apply MVVM pattern such as Windows 8 app, Windows phone app… When you use Xamarin (http://xamarin.com/) to develop cross platform applications with C#, maybe you want to use MVVM pattern too. In my last post 6 years ago, I introduced to you the concept of MVVM in ‘raw’ format which means no use of any external frameworks. Today I would like to make a supplementary post by introducing 2 MVVM frameworks for easing the use of MVVM pattern. The first one is Caliburn.Micro https://github.com/Caliburn-Micro/Caliburn.Micro and the second one is Mvvm Cross https://github.com/MvvmCross/MvvmCross . They’re both open source products and can be used in any commercial applications.

Continue reading C# – WPF MVVM DataBinding 2014

C# – Host Microsoft Chart in WPF application

How we provide our customers the way to display their data is a important feature of every software for data management. Maybe the users want to use Bar, Line, Pie, Pyramid chart… someone wants to display as 2D and the other wants 3D for his plotting. The financial prefer Kagi, Renko, Point and Figure chart… meanwhile the statisticians maybe use Bar and Column, Cylinder or just simple Line chart. Because of these numerously different requirements we need a stable chart library flexible for customizing and extending. We can make ourselves one or there are a lot of candidates out there in internet such as ZedGraph, Telerik component, DevExpress component… But my favor is Microsoft Chart included in .Net Framework. The components of Telerik, for example, are beautiful with their animations (in WPF) and have a lot of advance features. However the structure of this framework is not stable with breaking changes with new released versions. The Microsoft Chart provides us all simple features necessary for data representing and is very stable. We can use it on Windows Forms or WPF or even on ASP.NET website.

Continue reading C# – Host Microsoft Chart in WPF application

C# – Insert Images and Hyperlinks into RichTextBox in WPF

Like the name of control, the RichTextBox inheriting from TextBox control, allows user to enter and edit text. However it also provides more advanced formatting features than the standard TextBox, for example inserting rich media objects like images and hyperlinks. The objects (text, images, hyperlinks…) can be assigned directly to the control or can be loaded from a rich text format (RTF) file. We can also load data from an already opened data stream, edit and then save its content to RTF or ASCII file format. Moreover the RichTextBox control provides a number of properties we can use to apply formatting to any portion of text within the control as font, color, indent… In this small blog post I would like to demonstrate how I can parse Smiley code and Hyperlink in a RichTextBox.

After creating a normal WPF application, insert a TextBox and a RichTextBox as following XAML code

<Window x:Class="RichTextBox_Hyperlink.MainWindow"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	xmlns:local="clr-namespace:RichTextBox_Hyperlink"
	mc:Ignorable="d"
	Height="300"
	Width="300"
	Title="RichTextBox - Images and Hyperlinks"
	DataContext="{Binding Main, Source={StaticResource Locator}}">
...
<Grid x:Name="LayoutRoot">
	<Grid.RowDefinitions>
		<RowDefinition Height="5*"/>
		<RowDefinition Height="5*"/>
	</Grid.RowDefinitions>
	<TextBox x:Name="TextWithUrl" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" Grid.Row="0" />
	<RichTextBox IsDocumentEnabled="True" Grid.Row="1" local:RTBNavigationService.Content="{Binding Text, ElementName=TextWithUrl}">
	</RichTextBox>
</Grid>

My demo contains simply a TextBox for inputting plain text and the RichTextBox control will parse this plain text as I want. Therefore I bound the Text property of RichTextBox to the Text property of TextBox control. As you know that the Text property of RichTextBox in WPF is “invisible”. To “hook up” its content, I have to write a class with a DependencyProperty bound to this Text property and handle its Changed event to modify the text as it should be displayed

public static class RTBNavigationService
{
	public static string GetContent(DependencyObject d)
	{ return d.GetValue(ContentProperty) as string; }

	public static void SetContent(DependencyObject d, string value)
	{ d.SetValue(ContentProperty, value); }

	private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
	{
	...
	}
}

Now I have “hooked” the Changed event of Text property, then I go to the first Parse function: Smiley Code Parsing.

1. Smiley Code Parsing
As every Internet citizen knows, each smiley is bound with a smiley code. For each application there is a other smiley code set. In this small demo I just want to handle only one smiley code : ). That means when I type in TextBox : ), then the RichTextBox should show a smile icon.

private static readonly Regex regexSmilies = new Regex(@"(:\)(?!\)))");
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
	RichTextBox richTextBox = d as RichTextBox;
	if (richTextBox == null)
		return;

	
	string content = (string)e.NewValue;
	if (string.IsNullOrEmpty(content))
		return;

	richTextBox.Document.Blocks.Clear();

	int lastPos = 0;
	Paragraph block = new Paragraph();
	foreach (Match match in regexSmilies.Matches(content))
	{                
		if (match.Index != lastPos)
			block.Inlines.Add(content.Substring(lastPos, match.Index - lastPos));

		BitmapImage bitmapSmiley = new BitmapImage(new Uri("giggle.gif", UriKind.Relative));
		Image smiley = new Image();
		smiley.Source = bitmapSmiley;
		smiley.Width = bitmapSmiley.Width;
		smiley.Height = bitmapSmiley.Height;
		block.Inlines.Add(smiley);
		
		lastPos = match.Index + match.Length;                     
	}
	if (lastPos < content.Length)
		block.Inlines.Add(content.Substring(lastPos));
	richTextBox.Document.Blocks.Add(block);
	
	...
}

The code is pretty simple. First I need to find where the smiley code was entered. Then I just split the Text into 3 parts: before smiley, smiley and after smiley. The parts – before and after smiley – will be inserted as Text through the AppendText function. The smiley code will be firstly replaced with an image and then inserted into the paragraph. Appending these parts with each other I have something like this

RichTextBox - Images and Hyperlinks

2. Hyperlink Parsing
In the Smiley parsing, I use a paragraph to store and then append the objects (text, image) with each other. You can use this technique to parse hyperlink too. However I would like to introduce another way with TextPointer to parse hyperlinks in RichTextBox text.
The idea is same as above, I need to find all hyperlinks with Regex and then replace the text with a real hyperlink one which one can click on it. But instead of adding directly hyperlink object into a paragraph, I will mark these hyperlinks with TextPointer and create a hyperlink object for it.

private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
	...
	List<Hyperlink> results = new List<Hyperlink>();
	foreach (Match match in regexUrl.Matches(content))
	{
		TextPointer p1 = richTextBox.ToTextPointer(match.Index);
		TextPointer p2 = richTextBox.ToTextPointer(match.Index + match.Length);
		if (p1 == null || p2 == null)
		{
			//Donothing
		}
		else
		{
			(new Hyperlink(p1, p2)).Click += OnUrlClick;
		}
	}
}

private static void OnUrlClick(object sender, RoutedEventArgs e)
{
	Process.Start((sender as Hyperlink).NavigateUri.AbsoluteUri);
}

As you can see that I convert the start and end offsets of hyperlink to TextPointer and create a object of hyperlink with these TextPointers inclusive adding a Click handler for it. The ToTextPointer () function walks through all components of RichTextBox and converts the start/end offset of hyperlink to TextPointer.

public static TextPointer ToTextPointer(this RichTextBox rtb, int index)
{
	int count = 0;
	TextPointer position = rtb.Document.ContentStart.GetNextContextPosition(LogicalDirection.Forward).GetNextContextPosition(LogicalDirection.Forward);
	while (position != null)
	{
		if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
		{
			string textRun = position.GetTextInRun(LogicalDirection.Forward);
			int length = textRun.Length;
			if (count + length > index)
			{
				return position.GetPositionAtOffset(index - count);
			}
			count += length;
		}
		position = position.GetNextContextPosition(LogicalDirection.Forward);
	}
	return null;
}

At the end we have a RichTextBox which can parse smiley code and hyperlink dynamically. It’s very comfortable when using MVVM with data binding

RichTextBox - Images and Hyperlinks

The demo source code can be downloaded here “RichTextBox – Images and Hyperlinks

C#, WPF – Copy files with progress bar by CopyFileEx API

When we copy a lot of files to a folder we would like our program showing the copying progress with useful information, for example how does the copying run or how many file left to be copied. The managed function File.Copy does not allow us to monitor its process by providing any callback function. There are already in internet many articles show us how to copy files with progress bar in Windows Form. Therefor in this example below, I would like to make a demo with WPF. The core function of our example is the CopyFileEx API.
CopyFileEx Function copies an existing file to a new file, notifying the application of its progress through a callback function.
From the beginning, I thought it’s pretty simple but then I was stuck in a mess which takes me many hours to solve. The signature of CopyFileEx API in C# looks like following.

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName,
   CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref bool pbCancel,
   CopyFileFlags dwCopyFlags);

I took the signature from pinvoke.net but changed the “ref int pbCancel” to “ref bool pbCancel” so that the argument get more meaningful. Code to call to this API

bool bSuccess = CopyFileEx(lstSource[nIndex], m_strDestFile, new CopyProgressRoutine(CopyProgressHandler), IntPtr.Zero, ref m_bCancel, CopyFileFlags.COPY_FILE_RESTARTABLE);
if (!bSuccess)
{
	int error = Marshal.GetLastWin32Error();
	throw new Win32Exception(error);
}

Whereas the variable lstSource contains paths to all of source files, m_strDestFile is the folder where we want to copy to, m_bCancel is variable to cancel the copy progress when it is set to be true. In the callback function we have possibility to get how much data was already copied and other info.

private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long StreamByteTrans, uint dwStreamNumber, CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData)
{
	switch (reason)
	{
		case CopyProgressCallbackReason.CALLBACK_CHUNK_FINISHED:
			m_dtElapsedTime = DateTime.Now - m_dtStartTime;
			EventCopyHandler(this, new CopyEventArgs(((double)transferred / total) * 100, (transferred / 1024) / m_dtElapsedTime.TotalSeconds));
			return m_bCancel ? CopyProgressResult.PROGRESS_CANCEL : CopyProgressResult.PROGRESS_CONTINUE;                    
		default:                    
			return CopyProgressResult.PROGRESS_CONTINUE;
	}
}

You can see that the data was sent in chunk. As I remembered (if not wrong ^^) in my computer, the chunk size is about 0x10000 bytes. In this callback function we will update our progress bar and cancel if receiving cancel-event from user. That’s all about main ideas. I think it’s not difficult to understand. I would like now to talk more about 2 big problems which I met during programming.
1. WPF Control, exactly progress bar, does not update itself when copying
When I test to copy a big file, the complete GUI just completely freezes. The progress bar doesn’t run smoothly. It just jumps from 0 to 100. Thanks to the post of this blog http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh–update-wpf-controls.aspx , I solved the problem as following

private void UpdateProgress(int nPercent)
{
	pbBar.Value = nPercent;
	pbBar.Refresh();
	btnCopy.RefreshInput();
}

void cfewEngine_EventCopyHandler(CopyFileExWrapper sender, CopyEventArgs e)
{
	this.Dispatcher.Invoke(new UpdateProgressDelegate(UpdateProgress), new object[] { Convert.ToInt32(e.Percent) });            
}

public static class ExtensionMethods
{
	private static Action EmptyDelegate = delegate() { };
	public static void Refresh(this UIElement uiElement)
	{
		uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
	}

	public static void RefreshInput(this UIElement uiElement)
	{
		uiElement.Dispatcher.Invoke(DispatcherPriority.Input, EmptyDelegate);
	}
}

2. m_bCancel lost its value
When the user click to cancel copying, I set the m_bCancel to “true”. But in the callback function it has value “false” again. Until now I still do not understand why it losts its value. I solve the problem by adding “static” keyword to m_bCancel variable and it works. But I can not explain myself, why it turns to be false although I set it to true.

The complete source code you can download here “CopyFileEx Wrapper”

UPDATE 12.04.2012
– Fix code so that m_bCancel doesn’t have to be static.

Silverlight, WPF – ListBox Drag and Drop

During my development I need to implement the drag and drop feature in Silverlight. It’s pretty easy to make this feature work in Windows Form but it’s not simple to enable this feature on control in Silverlight. Therefore the developer team of Silverlight has developed a Silverlight toolkit to help us to alleviate our work. The Silverlight Toolkit is a collection of Silverlight controls, components and utilities made available outside the normal Silverlight release cycle. For more details about this toolkit you can read here http://silverlight.codeplex.com/.
In this example I would like to illustrate how we can use this toolkit to adapt the drag and drop to list box component of Silverlight. First you need to browse to URL above and install Silverlight Toolkit, then use Microsoft Expression Blend to add two list boxes to our application

Continue reading Silverlight, WPF – ListBox Drag and Drop

WPF – Use ZedGraph in WPF application

Maybe you already know about ZedGraph. ZedGraph is a set of classes, written in C#, for creating 2D line and bar graphs of arbitrary datasets http://sourceforge.net/projects/zedgraph/ . If you need some basic samples for using this library you can read a useful article at CodeProject http://www.codeproject.com/KB/graphics/zedgraph.aspx . However this library now only supports Windows Form Application. If you want to host a graph on WPF application, you can follow the steps in this blog below. The main idea of this method is host a graph in a User Control of Windows Form and then host this user control in WPF application.

Continue reading WPF – Use ZedGraph in WPF application

C#, WPF – Webservice Part I

When I studied WCF Services and wrote some examples for training, I would like to make some basic review about Web Services therefore today I decide to write some simple examples working with Web Services. I know that there are a lot of examples with Web Services on internet but I want to write my own one so that I can use it later. Anyway reading and understanding my own example and explanation is faster than reading from the other one. Let’s start with step by step instructions. This example I took from book “Datenbank-Programmierung mit Visual C# 2005” with some modifications. At the end of this example I will have a running Web Service and a client get its data to show and edit.

1. Open Visual Studio and create new project type ASP.NET Web Service called “OrderService”.
2. Copy and move file Company.mdb as our database into App_Data.
3. In Web.config file, edit “connectionStrings” and add our connection to our database

<connectionStrings>
	<add name="DataConnectionString" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Company.mdb;Persist Security Info = True" providerName="System.Data.Oledb"/>
</connectionStrings>

4. Remember set your project only running on x86 platform because OleDB does not support 64 bit OS. Add two web methods in our service to get data and let data be updated to database. The code looks little ugly but it works ^^.

private string strConnection = WebConfigurationManager.ConnectionStrings["DataConnectionString"].ToString();
[WebMethod]
public DataSet GetOrders(int CustomerNr, DateTime From, DateTime Till)
{
	DbProviderFactory provider = DbProviderFactories.GetFactory("System.Data.OleDb");
	DbConnection conn = provider.CreateConnection();
	conn.ConnectionString = strConnection;
	DbCommand cmd = provider.CreateCommand();
	cmd.Connection = conn;
	cmd.CommandText = "SELECT * FROM Orders WHERE CustomerNr = ? AND (EntranceDate BETWEEN ? AND ?)";
	DbParameter dbPar = cmd.CreateParameter();
	dbPar.ParameterName = "@CustomerNr";
	dbPar.DbType = DbType.Int32;
	dbPar.Value = CustomerNr;
	cmd.Parameters.Add(dbPar);

	dbPar = cmd.CreateParameter();
	dbPar.ParameterName = "@From";
	dbPar.DbType = DbType.Date;
	dbPar.Value = From;
	cmd.Parameters.Add(dbPar);

	dbPar = cmd.CreateParameter();
	dbPar.ParameterName = "@Till";
	dbPar.DbType = DbType.Date;
	dbPar.Value = Till;
	cmd.Parameters.Add(dbPar);

	DbDataAdapter da = provider.CreateDataAdapter();
	da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
	da.SelectCommand = cmd;
	DataSet dsOrder = new DataSet("OrderDS");
	conn.Open();
	da.Fill(dsOrder,"Orders");
	conn.Close();
	return dsOrder;
}

[WebMethod]
public void SetOrders(ref DataSet OrderDS)
{
	DbProviderFactory provider = DbProviderFactories.GetFactory("System.Data.OleDb");
	DbConnection conn = provider.CreateConnection();
	conn.ConnectionString = strConnection;
	DbCommand cmd = provider.CreateCommand();
	cmd.Connection = conn;
	cmd.CommandText = "SELECT * FROM Orders";
	DbDataAdapter da = provider.CreateDataAdapter();
	da.SelectCommand = cmd;
	da.ContinueUpdateOnError = true;
	DbCommandBuilder cb = provider.CreateCommandBuilder();
	cb.DataAdapter = da;
	conn.Open();
	da.Update(OrderDS.Tables["Orders"]);
	conn.Close();
}

5. Let’s compile and run our service. If everything goes, I’ll get the last result looks like following. Let’s test our GetOrders Web method.

6. Let’s add new project to our solution as our client. The new project is WPF Application “OrderClient”.
7. Use Microsoft Expression Blend 3 to design user interface as shown above. The user interface contain some labels, 3 buttons, 2 date picker and a data grid.
8. Right click on “OrderClient” project and “Add service reference”. On new opening dialog, click on Discover and choose Service in Solution and choose “OrdersService”.

9. Add handler to button click to load data and save changed data to our database.

private void btnLoadOrders_Click(object sender, System.Windows.RoutedEventArgs e)
{
	// TODO: Add event handler implementation here.
	try
	{
		int nCustNr = Convert.ToInt32(txtCustomer.Text);
		if (m_ServiceType == CallServiceTypes.ASYNCHRON)
		{
			OrdersService.GetOrdersCompleted += new EventHandler<OrderClient.OrdersServiceReference.GetOrdersCompletedEventArgs>(OrdersService_GetOrdersCompleted);
			OrdersService.GetOrdersAsync(nCustNr, dpFrom.DisplayDate, dpTill.DisplayDate);
		}
		else
		{
			m_dsOrders = OrdersService.GetOrders(nCustNr, dpFrom.DisplayDate, dpTill.DisplayDate);
			dgData.ItemsSource = m_dsOrders.Tables["Orders"].DefaultView;
		}
		//dgData.DataContext = dsTemp.Tables["Orders"];

	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

10. As you can see in the code above I use asynchronous and synchronous to get data. When using asynchronous method, for any reasons if the web service is not available, the method will not last until Timeout error raises but it will response immediately so that we do not wait. To use asynchronous method, we must configure our referenced service to auto create asynchronous operations.

The complete source code of example you can download here “Order Service

C#, WPF – Windows 7 Thumbnail Toolbar

During learning to develop myself a gadget for Windows 7, I would like to use some features of Windows 7 for my application. One of these features is enabling thumbnail of our application on toolbar as following

You can see in image above that I have a custom beautiful thumbnail with 4 buttons to navigate through the image gallery. To apply this feature in our application, I need a library called Microsoft API Code Pack http://code.msdn.microsoft.com/WindowsAPICodePack . In download package you can find a lot of examples relevant to many interesting features of Windows 7. The example below is extracted from this package but I made some modifications so that it works better.

1. Create a WPF application, add a StackPanel and 2 children: Image and ListBox control. The list box item template was also changed to contain an Image and a TextBlock. The TextBlock is set by the name of the image.

2. Add reference to Microsoft.WindowsAPICodePack.dll and Microsoft.WindowsAPICodePack.Shell.dll.
3. Test if I am running on Windows 7

public Window1()
{
	if (!TaskbarManager.IsPlatformSupported)
	{
		MessageBox.Show("This demo runs only on Windows 7");
		Application.Current.Shutdown();
	}
	InitializeComponent();
}

4. Add images to list box through data binding. The data was taken from ViewModel.

<ListBox x:Name="ImageList" ItemsSource="{Binding AllImages}" ItemTemplate="{DynamicResource ItemImageTemplate}" ItemsPanel="{DynamicResource PanelImageTemplate}" Height="167" />

5. Add 4 thumbnail toolbar button when window loads. These buttons will be used for navigating our gallery in thumbnail as shown in image above.

private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
	// TODO: Add event handler implementation here.
	m_btnToolbarFist = new ThumbnailToolbarButton(Properties.Resources.FirstImage, "First Image");
	m_btnToolbarFist.Enabled = true;
	m_btnToolbarFist.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(m_btnToolbarFist_Click);

	m_btnToolbarPrev = new ThumbnailToolbarButton(Properties.Resources.PreviousImage, "Previous Image");
	m_btnToolbarPrev.Enabled = true;
	m_btnToolbarPrev.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(m_btnToolbarPrev_Click);

	m_btnToolbarNext = new ThumbnailToolbarButton(Properties.Resources.NextImage, "Next Image");
	m_btnToolbarNext.Enabled = true;
	m_btnToolbarNext.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(m_btnToolbarNext_Click);

	m_btnToolbarLast = new ThumbnailToolbarButton(Properties.Resources.LastImage, "Last Image");
	m_btnToolbarLast.Enabled = true;
	m_btnToolbarLast.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(m_btnToolbarLast_Click);

	TaskbarManager.Instance.ThumbnailToolbars.AddButtons(new WindowInteropHelper(this).Handle, new ThumbnailToolbarButton[] { m_btnToolbarFist, m_btnToolbarPrev, m_btnToolbarNext, m_btnToolbarLast });
}

6. Add some code lines for navigating images in list. For example, the code handle to navigate to the last image in list.

void m_btnToolbarLast_Click(object sender, ThumbnailButtonClickedEventArgs e)
{
	ImageList.SelectedIndex = ImageList.Items.Count - 1;
	ImageList.Focus();
	if (ImageList.SelectedItem != null)
		ImageList.ScrollIntoView(ImageList.SelectedItem);
}

7. I would like to use the current selected image as our thumbnail. Therefore let’s take a snapshot of Image control and set it to taskbar through SetThumbnailcClip function.

void PictureBox_LayoutUpdated(object sender, EventArgs e)
{
	Vector vtPict = VisualTreeHelper.GetOffset(PictureBox);
	TaskbarManager.Instance.TabbedThumbnail.SetThumbnailClip(new WindowInteropHelper(this).Handle, new System.Drawing.Rectangle((int)vtPict.X, (int)vtPict.Y, (int)PictureBox.RenderSize.Width, (int)PictureBox.RenderSize.Height));
}

What I am still concerning is try to build the program exactly according to MVVM pattern. The complete source code you can download “WPF Win7 Thumbnail Demo