Click here to Skip to main content
Click here to Skip to main content

Architecture Guide: Windows Forms, Generics, Auto-Mapper, Entity Framework, Framework Design, and many more..

, 12 Dec 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Architecting a Windows Forms based system on top of a framework. This will help you develop a form based application faster.

DB is inside - DemoCustomerFrms\DB\Raptor_Core_Local_DB_Backup_17_11_2010. Check - Rocket Framework (.NET 4.0)  to see how this is being used in practise.

Table of Contents

  1. Introduction
  2. Background
  3. How You Use a Framework?
  4. Let's Have a Look at Our Demo Framework
  5. How We Build Our Framework Gradually?
  6. High Level Design Overview
  7. Let's look at the ‘Demo.Framework’ Module Design
  8. Have a Look at the ‘BaseGridView’ Code Below
  9. Let's look at the ‘Demo.Data’ Module Design
  10. Let's look at the ‘Demo.Core’ Module Design
  11. Let's look at the ‘Demo.Core.UserControls’
  12. Module Design Implementation of Data Controls
  13. Final Note
  14. History

Introduction

Web system designing is well supported with many online materials. In contrast to that, support materials available for Windows-Forms based (desktop applications) system designing is less. In 1980s, during the era of two-tier systems, desktop applications ruled the software world. Now the time has changed and software geeks are now focused on web systems, leaving developers to design desktop applications at their will. Today you hardly see any architectural discipline being adopted in desktop applications. Therefore I thought of shedding some light over this ignored sector to improve the designing aspect of desktop applications.

In this attempt, I will demonstrate architecting a simple desktop application. Additionally, I will also develop a reusable framework that you can use to develop any desktop application.

When I talk about ‘framework’, you may have thought what a framework really is. I see there are many misinterpretations around the term ‘framework’. So I will give you an introduction to ‘framework’ too. That I will do at the early part of this write-up. But even before that, let me tell you how the idea to write this article started.

Background

We, in our company, are developing a large Windows Forms based application on .NET Framework 4.0 using Visual Studio 2010 these days. In that, we had the need to develop an administrative user interface (to do CRUD operations of master records), where users with certain rights can directly edit certain elements of the database tables. So we needed a set of screens, where they can edit the records of DB tables. One such screen is shown below for your reference. You may develop this screen in a matter of 20 minutes using our 'framework'.

windows_form__EF_grid/FormScreen.jpg

During the initial stages of this project, as usual, I spent a few days researching to find the right mix of technologies and design approaches to form the design of this system. I thought of developing a generic framework having the main goal to support editing of DB records. That framework was planned in such a manner that we can use that as the basis for any 'Desktop Application' development. The main goal of this writing is to introduce that ‘framework’ to the CodeProject community.

I thought that the system architecture not only should support editing database tables directly but also support dealing with custom business objects that use many fields from different tables too. Developing a generic 'framework' to support this is nearly impossible as different domains have different business needs. Therefore I thought that it is important to introduce multiple ‘wrapping’ layers on top of the generic framework to support handling domain specific needs. In other terms, this means we need a domain specific framework on top of the generic framework. That is to implement unique domain specific features of systems. So going forward, there will be several domain specific frameworks adding to this library. Additionally, to support customers' very specific highly customized unique requirements, I planned to have another layer on top of both the generic framework and the domain specific framework.

If everything goes well, once this 'architecture’ is stable, when a new customer comes, we just have to get a copy of the generic framework and the respective domain specific framework from our software store and spend a few days adding customer specific features to it before bundling everything to form the beta version of the release. Doesn't that sound exciting?

How to Use a Framework?

windows_form__EF_grid/Skeliton.png

Let’s examine the picture above. It is a framework and fairly easily you can form a room in it. Then with a little more work you can extend it to form a complex of rooms. Then you can develop a few extensions to it to form either a 'Motel', 'Hotel', or a luxury apartment complex. This is how you use a framework to build something quicker. This very same concept is what we are going to use to build our software system too.

This concept of building on a framework is not new. Even the language you use, .NET/C#, is a framework. Not only that, .NET has newer frameworks built on top of older frameworks too. In the next part of the article you will see how the .NET Framework 3.0 is being built on top of .NET Framework 2.0.

Let's Have a Look at Our Demo Framework

windows_form__EF_grid/DemoFramework.jpg

The picture shows how Microsoft has built .NET Framework 3.0 on top of .NET Framework 2.0. This shows how a framework can be used to build another on top of it.

As in the picture above, we will be building our framework on top of .NET Framework 4.0. That is the latest version of the .NET Framework family.

How We Build Our Framework Gradually?

windows_form__EF_grid/DemoFrameworkCustomized.jpg

This shows a strategy that you can use to develop a ‘framework’ without spending too much of your time initially. Firstly you need to have the guts to say ‘NO’ to the piles of the ever growing 'What if' type requirements that people around you want to add to the ‘framework’. You need to define the boundaries of the framework. Then you need to have some strategies in place so that you can build this system without a waste of your time.

As you can see in the picture, you have to identify a set of core features for the main framework. Then let the domain specific framework auto-build through every custom implementation.

High Level Design Overview

windows_form__EF_grid/PackageDiagram.jpg

This is the package diagram of our system. I have used some color coding to make it easier for you to understand.

As you can see, there are a few modules being used to developed this system. You can see the generic 'Demo.Framework' given right at the top. Then by using that, the core business logic as well as the user control libraries are formed. ‘Demo.Common’ is common for all and something that we will be sharing across multiple (all) packages. The data access layer (Demo.Data) library is developed using Microsoft ADO.NET Entity Framework.

Let's Look at the ‘Demo.Framework’ Module Design

Enough of talking, let's jump right into the water now. Don't be afraid, I know for a fact that some people are born afraid of system architecture. I too had it for ‘Chemistry’. I know for a fact that I didn’t have the right start to it. In the software world too, I have seen overly designed systems with never ending class hierarchies. Some of these systems are far more complicated for their requirements. But here in our design, I have kept it very simple. I wanted everyone to understand, be able to maintain, and also upgrade the system easily.

This design has a few but valuable 'interfaces'. Do not think that these interfaces make the design look complex or elegant, rather I have added them with valid reasons and to achieve certain things that wouldn’t have been possible otherwise. I will explain those design moves later in this article.

windows_form__EF_grid/Demo.Framework.png

There are seven class interfaces that are being used here. As you may have heard, in general an ‘interface’ separates the definition of an object from its implementation. If you think of an interface as a contract, it is clear that both sides of the contract have a role to play. The publisher (or the framework side of the equation) of the interface agrees never to change that interface, and the implementer (or the custom implementation side of the equation) agrees to implement the interface exactly as it was designed. This helps using the interface across many other generic classes even without knowing their implementation.

  • IHandler<V> - This is the generic interface that is used to implement all handler classes. Classes of type ‘Handler’ are the ones that are used to implement handlings for all business objects of this system.

  • IMapper<V, D> - This wraps a third party library called Auto-Mapper. The Auto-Mapper (ref: http://automapper.codeplex.com/) uses a convention-based matching algorithm to match up a source object to its destination object values.

  • IObject – This interface is what implements the abstract BaseObject which is used as the base class for all business objects.

  • Note: V stands for the view or business object whereas D stands for data objects or a table of the database.

  • IDataContainer<V> - This is what is used to implement BaseData<V>, the generic user control. I must tell you that Microsoft is still not ready to support applying object oriented programming concepts for user controls or developing generic user controls. The IDE starts giving you trouble immediately after it sees the ‘<’ mark. The beauty of the generic implementation made me ignore that hassle. As you are following my directions you will also have to face troubles that the Visual Studio IDE (I saw this bug was reported around 2003 but is still there in VS 2010 too) is going to throw at you.

  • IGridView – This is the interface that is used to implement the generic BaseGridView<H, V>. In this H is of type IHandler<V> whereas V is of type BaseObject.

This framework is elegantly designed with minimum complexity. I know that some of you still may find it difficult to understand. If you don’t have expertise dealing with generics, interfaces, etc., then just find the pattern to using this framework and start using it, then slowly you will understand it. Even today there are many developers take advantage of this to build their applications without having a clue about the design of the framework or generics or interfaces. Once understood, the pattern of the design itself will guide you to use it.

Have a look at the ‘BaseGridView’ code below

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Demo.Framework
{
    public abstract partial class BaseGridView<H, V> : BaseControl, IGridView
        where H : IHandler<V>
        where V: BaseObject
    {
        public event DataGridViewCellEventHandler DataRowSelected;
        public BaseGridView(H h)
        {
            InitializeComponent();
            _hadler = h;
        }

        private H _hadler;
        public virtual void LoadData()
        {
            this.DataList = _hadler.GetAll();
        }

        private V _selectedItem;
        public V SelectedItem
        {
            get { return _selectedItem; }
        }

        private List<V> _originalList = null;
        private List<V> _dataList;
        public List<V> DataList
        {
            get { return _dataList; }
            set
            {
                _dataList = value;
                this.dataGridViewMain.DataSource = null;
                if (_dataList == null) return;
                this.dataGridViewMain.Columns.Clear();

                this.dataGridViewMain.AutoGenerateColumns = true;
                this.dataGridViewMain.DataSource = this._dataList;
                OnHideColumns(ref dataGridViewMain);
                if (_dataList.Count > 0)
                {
                    int cCount = this.dataGridViewMain.Columns.Count;
                    foreach (KeyValuePair<string, object> item in _dataList[0].Data)
                    {
                        DataGridViewTextBoxColumn mRef = new DataGridViewTextBoxColumn();
                        mRef.HeaderText = item.Key;
                        this.dataGridViewMain.Columns.Add(mRef);
                    }

                    for (int i = 0; i < dataGridViewMain.RowCount; i++)
                    {
                        int c = cCount;
                        IObject boundItem = (V)dataGridViewMain.Rows[i].DataBoundItem;
                        foreach (KeyValuePair<string, object> item in boundItem.Data)
                            this.dataGridViewMain[c++, i].Value = item.Value;
                    }
                }
            }
        }

        protected virtual void OnHideColumns(ref DataGridView dataGridView)
        {
            dataGridView.Columns["Id"].Visible = false;
            dataGridView.Columns["Data"].Visible = false;
            dataGridView.Columns["SourcePoco"].Visible = false;
        }

        public string Heading
        {
            get { return groupBoxMain.Text; }
            set { groupBoxMain.Text = value; }
        }

        protected List<V> Search(string query)
        {
            List<V> list = new List<V>();
            string[] qItems = query.Split(' ');
            foreach (V item in _dataList)
            {
                for (int i = 0; i < qItems.Length; i++)
                    if (item.FoundIt(qItems[i]))
                        list.Add(item);
            }
            return (list.Count > 0) ? list : null;
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            if (_originalList == null)
            {
                _originalList = _dataList;
                return;
            }

            string s = this.textBoxSearch.Text.Trim();
            this.dataGridViewMain.Columns.Clear();
            if (string.IsNullOrEmpty(s))
                this.DataList = _originalList;
            else
                this.DataList = this.Search(s);
        }

        private void dataGridViewMain_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
                _selectedItem = (V)dataGridViewMain.Rows[e.RowIndex].DataBoundItem;

            if (DataRowSelected != null)
                DataRowSelected(_selectedItem, e);
        }

        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            LoadData();
            this.textBoxSearch.Text = "";
        }
    }
} 

I want you to focus on the top part of this generic abstract class named BaseGridView<H>. In the implementation, the constructor is being used to get the implemented version of the handler (H) passed on to it. Since all handlers of our system implement IHandler, the system has the advantage of using the built-in methods of handlers via the IHandler interface. Interestingly we do this even without knowing the actual implementation of it. This is a very interesting part of our code. You will be able to understand this design approach more as you read along this article. At the same time I invite you to carefully examine the source code too.

BaseHandler<V, D> - This abstract class implements both IHandler and IMapper interfaces. It contains the generic implementation for handling business objects. All these classes and interfaces use two generics namely V and D of type BaseObject and EntityObject. The BaseHandler associate with the IRepository<D> interface too. That association is used to hide the repository implementation. The repository object which passes on to this at the time of implementing a specific handler is used to retrieve data related to a particular data object from the database. There the Auto-Mapper is used to map them from D of type EntityObject to V of type BaseObject and pass that on to the next layer. The implementation of IRepository<D> is done under the Demo.Data library. I will explain that part later.

The base classes help us to do the generic implementation once and reuse them with multiple types.

Let's Look at the ‘Demo.Data’ Module Design

The system uses the ADO.NET Entity Framework (.NET 4) to generate the data access layer (ref: http://msdn.microsoft.com/en-us/data/ee712907.aspx). I also went on to use a T4 template, but later found that the special generic repository implementation that I am introducing here is not easily doable with a T4 template. So I just use the default code that Entity Framework generates. For your understanding, have a look at the generic repository code below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Linq.Expressions;
using System.Data;
using System.Data.Objects.DataClasses;
using System.Data.Common;
using Demo.Framework;

namespace Demo.Data
{
    public sealed class DemoRepository<T> : IRepository<T>
        where T : EntityObject
    {
        static readonly DemoRepository<T> instance
            = new DemoRepository<T>(new DemoCoreEntities());
        private static readonly Object _lockObject = new Object();
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static DemoRepository()
        {
            if (_lockObject == null)
                _lockObject = new Object();
        }

        public static DemoRepository<T> Instance
        {
            get
            {
                return instance;
            }
        }

        DemoRepository(ObjectContext repositoryContext)
        {
            _repositoryContext = repositoryContext ?? new DemoCoreEntities();
            _objectSet = _repositoryContext.CreateObjectSet<T>();
        }

        private static ObjectContext _repositoryContext;
        private ObjectSet<T> _objectSet;
        public ObjectSet<T> ObjectSet
        {
            get
            {
                return _objectSet;
            }
        }

        #region IRepository Members

        public IRepository<T> GetRepository()
        {
            return Instance;
        }

        public void Add(T entity)
        {
            lock (_lockObject)
            {
                this._objectSet.AddObject(entity);
                _repositoryContext.SaveChanges();
                _repositoryContext.AcceptAllChanges();
            }
        }

        public void Update(T entity)
        {
            lock (_lockObject)
            {
                _repositoryContext.ApplyOriginalValues(((IEntityWithKey)entity)
                    .EntityKey.EntitySetName, entity);
                _repositoryContext.Refresh(RefreshMode.ClientWins, _objectSet);
                _repositoryContext.SaveChanges();
                _repositoryContext.AcceptAllChanges();
            }
        }

        public void Delete(T entity)
        {
            lock (_lockObject)
            {
                this._objectSet.DeleteObject(entity);
                _repositoryContext.Refresh(RefreshMode.ClientWins, _objectSet);
                _repositoryContext.SaveChanges();
                _repositoryContext.AcceptAllChanges();
            }
        }

        public void DeleteAll()
        {
            _repositoryContext
                .ExecuteStoreCommand("DELETE " + _objectSet.EntitySet.ElementType.Name);
        }

        public IList<T> GetAll()
        {
            lock (_lockObject)
            {
                return this._objectSet.ToList<T>();
            }
        }

        public IList<T> GetAll(Expression<Func<T, bool>> whereCondition)
        {
            lock (_lockObject)
            {
                return this._objectSet.Where(whereCondition).ToList<T>();
            }
        }

        public T GetSingle(Expression<Func<T, bool>> whereCondition)
        {
            lock (_lockObject)
            {
                return this._objectSet.Where(whereCondition).FirstOrDefault<T>();
            }
        }

        public IQueryable<T> GetQueryable()
        {
            lock (_lockObject)
            {
                return this._objectSet.AsQueryable<T>();
            }
        }

        public long Count()
        {
            lock (_lockObject)
            {
                return this._objectSet.LongCount<T>();
            }
        }

        public long Count(Expression<Func<T, bool>> whereCondition)
        {
            lock (_lockObject)
            {
                return this._objectSet.Where(whereCondition).LongCount<T>();
            }
        }

        #endregion
    }
}

The code you see above is a special one. I am trying to use the 'Generic' repository as effectively as possible. As you can see, the repository is implemented as a single object. The thread safe version of the Singleton design pattern is used to implement the repository. In addition to that, an additional protection is done using _lockObject to allow concurrent access to the repository. Just to demonstrate the usage of SQL commands directly inside the repository, the DeleteAll() method is written.

Let's Look at the ‘Demo.Core’ Module Design

‘Demo.Core’ is used to implement all business objects and their handling functions. Going along with the MVC architecture, I thought of naming all business objects with the ‘View’ suffix. So in the library you will find two types of classes. One is of type handler (which is a variant of the Service class of the MVC architecture) and the other is of View type. Handler type classes have all operations related to a particular view object. Let’s open the HandlerApplicationUser class and see what we find inside it.

windows_form__EF_grid/Demo.Core.png

The class HandlerApplicationView is as follows. It is pretty much an empty class. One requirement is to pass the correct instance of the repository to its base class. In addition to that if you want to do special mappings from the ‘data object’ to the ‘business object’ or vice versa, then you need to update the mapping expression by using either the ForwardMap or BackwardMap method.

E.g., for BackwarMap: If you have ‘FirstName’, ‘Initials’, and ‘LastName’ in one table, then the respective data object will have three fields with the same names. If you want these three fields of the dataobject to be mapped to a new field called Name of the business object then you can use the provided BackwardMap mapping expression. As you can see, the method BackwardMap has IMappingExpression<ApplicationUser, ApplicationUserView>, which has, in our case, detail to map ApplicationUser to ApplicationUserView.

Are lambda expressions bothering you? That is not difficult at all, you just have to understand the pattern; once understood, there is nothing difficult about lambda expressions.

The LogPrefix property finds the handle class below is for log4net. If you look at the LoggerBase class inside the Common folder of the framework library, where you will understand that ‘Logger Base’ wraps log4net functions to gain flexibility to replace it with another.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.Data;
using AutoMapper;
using Demo.Core.Models;
using Demo.Framework;

namespace Demo.Core
{
    public class HandlerApplicationUser : BaseHandler<ApplicationUserView, ApplicationUser>
    {
        public HandlerApplicationUser()
            : base(DemoRepository<ApplicationUser>.Instance)
        {
        }

        public override void ForwardMap(IMappingExpression<ApplicationUserView, ApplicationUser> mappingExpression)
        {
            mappingExpression
               .ForMember(dest => dest.ApplicationUserId, opt => opt.MapFrom(src => src.Id))
               .ForMember(dest => dest.Gender, opt => opt.MapFrom(src => (src.SelectedGender.Key == 1) ? true : false))               
               .ForMember(dest => dest.AdditionalData, opt => opt.MapFrom(src => (src.Data != null) ? src.Data.ToString() : ""));
        }

        public override void BackwardMap(
          AutoMapper.IMappingExpression<ApplicationUser, ApplicationUserView> mappingExpression)
        {
            mappingExpression
                .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.ApplicationUserId))
                .ForMember(dest => dest.SelectedGender, opt => opt.MapFrom(src => 
                  (src.Gender) ? new KeyValuePair<int, string>(1, "Male") : 
                  new KeyValuePair<int, string>(2, "Female")))
                .ForMember(dest => dest.SourcePoco, opt => opt.MapFrom(src => src))
                .ForMember(dest => dest.Data, opt => 
                  opt.MapFrom(src => AdditionalData.Resolve(src.AdditionalData)));
        }

        protected override Type LogPrefix
        {
            get { return this.GetType(); }
        }
    }
}

Let's look at the ‘Demo.Core.UserControls’ module design

This is where we develop all user controls. There again, as I said before, I am using generics extensively. But the design approach is pretty much like as it was with the above modules. So I will leave it up to you to look at the source code and understand it.

ApplicationUserData – This is a user control created by extending BaseData. This is where you will have textboxes, dropdowns, and labels allowing viewing, editing of business objects. There are a few steps that you need to follow when creating such a data control.

  1. Create the business object (name it ApplicationUserView).
  2. Create the handler class to handle the business object (name it HandlerApplicationUser).
  3. Add a new ‘Data Source’ by choosing ‘Object’ as the source (look at the screen below, you need to click on 'New Data Source' here). That will let you choose objects that can be used to generate the required data-bound control. You need to find the correct class library first and then select the right business object to create this new ‘Data Source’ (in our case, I have picked 'ApplicationUserView' as the source object).

windows_form__EF_grid/NewDataSource.PNG

  1. Add a new user control giving a standard name like <name of the business object>Data.cs (in our case, it was 'ApplicationUserData').
  2. Drag the whole view on to the user control and delete the ones that you don't want the user to view/edit on to the user control.
  3. Navigate to the source code of this newly added user control and change the parent class from “: UserControl” to “: BaseData<name of the business object>” (in our case it was BaseData<ApplicationUserView>). This change will make you override three methods as explained in the “Implementation of Data Controls” section below.

Note: Editing of these user controls using the IDE is not possible as visual studio does not understand generic type user controls. If you want to edit the data controls after they are built then you need to comment all three overridden methods and change the parent class back to “UserControl”. This will allow you to use the IDE for control editing. Once the editing is completed you need to role the changes back to their originals.

ApplicationUserDataGridView – This user control is capable of listing down a set of business objects. It also has a generic search. You can control the name of the columns of the grid by using DisplayNameAttribute. Other than that this has nothing much for the one which uses it to do. You can check the source code to understand the various things possible to be done here. One thing to note here is that you can use the method name OnHideColumns if you want to hide a particular column just before displaying.

ApplicationUserManager – This is the main manager control that helps you do all CRUD operations related to a business object. You just have to pass a few parameters up to the base class and that will take care of the rest for you.

Implementation of Data Controls

If you have to write any code in this library that is only inside the corresponding data control. I have given you one such implementation below.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Demo.Framework;
using Demo.Core.Models;
using Demo.Common;


namespace Demo.Core.Controls.ChildControls
{
    public partial class ApplicationUserData : BaseData<ApplicationUserView>
    {
        public ApplicationUserData()
        {
            InitializeComponent();
        }

        public override void SetBindingSource(ref BindingSource DemoBindingSource)
        {
            DemoBindingSource = this.applicationUserViewBindingSource;
        }


        public override ApplicationUserView MapIt(int Id)
        {
            ApplicationUserView apView = this.BindedView;
            apView.Id = Id;
            apView.UserName = this.userNameTextBox.Text;
            apView.Password = this.passwordTextBox.Text;
            apView.CustomerId = NullHandler.ConvertToInt(this.customerIdTextBox.Text);
            apView.SelectedGender = (KeyValuePair<int, string>)this.genderCombo1.SelectedItem;
            apView.FirstName = this.firstNameTextBox.Text;
            apView.ShortName = this.shortNameTextBox.Text;
            apView.MiddleName = this.middleNameTextBox.Text;
            apView.LastName = this.lastNameTextBox.Text;
            apView.StatusTypeId = NullHandler.ConvertToInt(this.statusTypeIdTextBox.Text);
            apView.LastLoginDateTime = this.lastLoginDateTimeDateTimePicker.Value;
            apView.Email = this.emailTextBox.Text;
            apView.Phone = this.phoneTextBox.Text;
            return apView;
        }

        protected override void _DemoBindingSource_DataSourceChanged(object sender, EventArgs e)
        {
            if (this.BindedView != null)
                this.genderCombo1.SelectedItem = this.BindedView.SelectedGender;
        }
    }
}

Final Note

The demonstration provided here is "as is" without warranty of any kind. I make no warranties, express or implied, that the source code given here is free of error or that they will meet your requirements for any particular application. It is up to you to evaluate, learn, review, and use it as applicable.

History

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nirosh
Architect MAS Holdings
Sri Lanka Sri Lanka
In-depth coverage of Microsoft .Net, Cloud and many other cutting-edge Technologies.
 
- The Mandelbrot set – someone has called it the thumb-print of God – is one of the most beautiful and remarkable discoveries in the entire history of mathematics. My profile picture is generated with that equation.
 
You may contact Nirosh for Consultations, Code Reviews and Architecture Guide Workshops via c_nir*o*sh@hotmail.com (Remove * to use)
 

View Nirosh L.W.C.'s profile on LinkedIn
Follow on   Twitter   Google+

Comments and Discussions

 
QuestionComplex and technical PinmemberTomaž Štih18-Dec-13 23:51 
AnswerRe: Complex and technical PinprofessionalNirosh19-Dec-13 0:42 
AnswerRe: Complex and technical PinprofessionalNirosh19-Dec-13 22:10 
GeneralMy vote of 5 PinmvpRahul Rajat Singh12-Dec-13 20:03 
GeneralNice! PinprofessionalBrisingr Aerowing14-Apr-13 4:43 
GeneralMy vote of 5 PinmemberRahul Rajat Singh26-Jun-12 18:28 
QuestionUnable to use the data file [modified] Pinmemberbikramiter23-Sep-11 19:04 
AnswerRe: Unable to use the data file Pinmemberbikramiter25-Sep-11 1:32 
GeneralFailed to run Pinmemberangels77718-Apr-11 20:36 
GeneralRe: Failed to run PinmemberNirosh19-Apr-11 18:11 
GeneralColumn Sorting PinmemberAndre Basco5-Apr-11 21:42 
Hi! How will you perform Column Sorting?
 
I saw the Property, SortWith, but I am messing up with the Parameters, and I don't know when should I fill the property...
I tried to set the SortMode of the Columns I wanted to sort with Automatic, but it the Grid doesn't react with it...
 
thanks!
GeneralRe: Column Sorting PinmemberNirosh6-Apr-11 19:59 
GeneralRe: Column Sorting PinmemberAndre Basco6-Apr-11 23:03 
GeneralRocket Framework is much feature rich.. PinmemberNirosh6-Apr-11 20:02 
GeneralGridView with control PinmemberArrianne Amoroso4-Apr-11 18:25 
GeneralRe: GridView with control PinmemberNirosh5-Apr-11 18:11 
Questionhow to call store procedures? Pinmembermartianb24-Mar-11 0:10 
AnswerRe: how to call store procedures? PinmemberNirosh24-Mar-11 21:19 
QuestionThanks for the article. But I have a question for you Pinmemberpetershaw99-Feb-11 18:25 
AnswerRe: Thanks for the article. But I have a question for you [modified] PinmemberNirosh9-Feb-11 22:04 
Generalgreat Pinmembermrpas29-Jan-11 15:59 
GeneralGood one PinmemberShahriar Iqbal Chowdhury28-Dec-10 3:36 
GeneralMy Vote of 5 Pinmembersucram28-Dec-10 2:12 
GeneralMy vote of 5 PinmvpEddy Vluggen28-Dec-10 0:07 
GeneralMy vote of 5 Pinmemberprasad0228-Dec-10 0:00 
GeneralMy vote of 5 Pinmemberiosifdohi29-Nov-10 20:51 
GeneralRe: My vote of 5 PinmemberNirosh30-Nov-10 16:37 
GeneralMy vote of 5 PinmemberSakshi Smriti29-Nov-10 17:15 
GeneralRe: My vote of 5 PinmemberNirosh30-Nov-10 16:36 
GeneralMy vote of 5 Pinmemberrht34122-Nov-10 4:34 
GeneralRe: My vote of 5 PinmemberNirosh24-Nov-10 16:13 
GeneralMy vote of 5 Pinmemberlinuxjr22-Nov-10 2:36 
GeneralRe: My vote of 5 PinmemberNirosh24-Nov-10 16:12 
GeneralMy vote of 5 PinmemberGermyan21-Nov-10 22:55 
GeneralRe: My vote of 5 PinmemberNirosh24-Nov-10 16:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.141029.1 | Last Updated 12 Dec 2013
Article Copyright 2010 by Nirosh
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid