Click here to Skip to main content
15,884,473 members
Articles / Web Development / ASP.NET

Developing Next Generation Smart Clients using .NET 2.0 working with Existing .NET 1.1 SOA-based XML Web Services

Rate me:
Please Sign up or sign in to vote.
4.96/5 (134 votes)
16 Aug 200540 min read 1.2M   3.9K   462  
Comprehensive guide to development of .NET 2.0 Smart Clients working with existing Service Oriented Architecture based XML web services, fully utilizing the Enterprise Library
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using SmartInstitute.Client.Automation.Documents;
using SmartInstitute.ObjectModel;
using SmartInstitute.Automation.Commands.Framework;
using SmartInstitute.Client.Automation.Commands.Students;
using SmartInstitute.Automation.Commands.Students;

namespace SmartInstitute.Automation.Documents.MiscDocuments
{
	public partial class SendReceiveUI : DocumentUIBase
	{
		/// <summary>
		/// Return the students list from the document
		/// </summary>
		private IList<StudentModel> _Students
		{
			get { return (base.Document as SendReceiveDocument).Students; }
			set { (base.Document as SendReceiveDocument).Students = value; }
		}

		public SendReceiveUI()
		{
			InitializeComponent();
		}

		internal override bool AcceptData(object data)
		{
			this._Students = data as IList<StudentModel>;
			this.StartSendReceive();

			return true;
		}

		private void StartSendReceive()
		{
			// Populate the listview with students
			this.tasksListView.Items.Clear();
			foreach (StudentModel student in this._Students)
			{
				ListViewItem item = new StudentListViewItem(student);
				this.tasksListView.Items.Add(item);
			}

			// Initialize progress bar
			this.progressBarControl.Maximum = this._Students.Count;
			this.progressBarControl.Value = 0;
			this.UpdateProgressStatus();

			// Start background synchronization
			worker.RunWorkerAsync();
		}

		private void SendReceiveUI_Load(object sender, EventArgs e)
		{
			this.StartSendReceive();
		}

		private void errorsListBox_DrawItem(object sender, DrawItemEventArgs e)
		{
			Rectangle bounds = e.Bounds;
			bounds.Inflate(-4, -2);

			float left = bounds.Left;

			e.Graphics.FillRectangle(Brushes.White, e.Bounds);

			if (e.State == DrawItemState.Focus
				|| e.State == DrawItemState.Selected)
				ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds);
			
			e.Graphics.DrawImage(this.imageList1.Images[3], new PointF(left, bounds.Top));
			
			left += this.imageList1.Images[3].Width;
			
			RectangleF textBounds = new RectangleF( left, bounds.Top, bounds.Width, bounds.Height);
			
			e.Graphics.DrawString(this.errorsListBox.Items[e.Index] as string,
				this.errorsListBox.Font, Brushes.Black, textBounds);

			e.Graphics.DrawLine(Pens.LightGray, e.Bounds.Left, e.Bounds.Bottom, 
				e.Bounds.Right, e.Bounds.Bottom);
		}

		private void worker_DoWork(object sender, DoWorkEventArgs e)
		{
			// This method will run on a thread other than the UI thread.
			// Be sure not to manipulate any Windows Forms controls created
			// on the UI thread from this method.

			this.BackgroundThreadWork();
		}

		/// <summary>
		/// This method performs the background synchronization by synchronizing
		/// each queued model for sending to the web service.
		/// 
		/// No UI Update from this function.
		/// </summary>
		private void BackgroundThreadWork()
		{
			foreach (StudentModel model in this._Students)
			{
				// Do the synchronization
				try
				{
					// 1. Send changes
					worker.ReportProgress((int)StudentListViewItem.StatusEnum.Sending, model);

					ICommand saveCommand = new SaveStudentCommand(model.Profile);
					saveCommand.Execute();

					// 2. Receive changes
					worker.ReportProgress((int)StudentListViewItem.StatusEnum.Receiving, model);

					ICommand loadCommand = new LoadStudentDetailCommand(model.Profile.ID);
					loadCommand.Execute();

					// 3. Complete 
					model.IsDirty = false;
					model.NotifyChange("Reloaded");
					model.LastErrorInSave = string.Empty;
					worker.ReportProgress((int)StudentListViewItem.StatusEnum.Completed, model);
				}
				catch (Exception x)
				{
					model.LastErrorInSave = x.Message;
					worker.ReportProgress((int)StudentListViewItem.StatusEnum.Error, model);
				}
			}
		}

		private class StudentListViewItem : ListViewItem
		{
			public enum StatusEnum
			{
				Sending,
				Receiving,
				Completed,
				Error
			}

			public StudentListViewItem.StatusEnum Status = StatusEnum.Sending;
			public StudentModel Model;	
			
			public StudentListViewItem(StudentModel model)
				: base(model.ToString(), 0)
			{
				this.Model = model;
				this.Refresh();

				base.SubItems.Add(new ListViewSubItem(this, model.ToString()));
				base.SubItems.Add(new ListViewSubItem(this, ""));
			}

			public void Refresh()
			{
				if (this.Status == StatusEnum.Sending)
					this.Sending();
				else if (this.Status == StatusEnum.Receiving)
					this.Receiving();
				else if (this.Status == StatusEnum.Error)
					this.Error();
				else if (this.Status == StatusEnum.Completed)
					this.Done();
			}
			public void Done()
			{
				base.ImageIndex = 1;
				base.SubItems[1].Text = "Completed";
			}

			public void Error()
			{
				base.ImageIndex = 2;
				base.SubItems[1].Text = "Error: " + this.Model.LastErrorInSave;

				base.ToolTipText = base.SubItems[1].Text;
			}

			public void Sending()
			{
				if (base.SubItems.Count < 2)
					base.SubItems.Add(new ListViewSubItem(this, "Sending..."));
				else
					base.SubItems[1].Text = "Sending...";
			}

			public void Receiving()
			{
				base.SubItems[1].Text = "Receiving...";
			}
		}

		private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			// Find the list view item which is hosting the specified model
			foreach (StudentListViewItem item in this.tasksListView.Items)
			{
				if (Object.ReferenceEquals(item.Model, e.UserState))
				{
					StudentModel model = e.UserState as StudentModel;
					if ( null != model.LastErrorInSave && model.LastErrorInSave.Length > 0)
					{
						this.AddError(model.LastErrorInSave);
					}

					item.Status = (StudentListViewItem.StatusEnum)e.ProgressPercentage;
					item.Refresh();
				}
			}

			// Increase progress bar upon success/failure, but not for intermediate progress
			if( (int)StudentListViewItem.StatusEnum.Completed == e.ProgressPercentage
				|| (int)StudentListViewItem.StatusEnum.Error == e.ProgressPercentage )
				this.progressBarControl.Increment(1);

			this.UpdateProgressStatus();

		}

		private void UpdateProgressStatus()
		{
			this.statusLabel.Text = string.Format(this.statusLabel.Tag as string,
				this.progressBarControl.Value, this.progressBarControl.Maximum);
		}

		private void AddError(string errorMsg)
		{
			this.errorsListBox.Items.Add(errorMsg);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect BT, UK (ex British Telecom)
United Kingdom United Kingdom

Comments and Discussions