Click here to Skip to main content
15,896,606 members
Articles / Desktop Programming / WPF

WPF CRUD Generator (Scaffolding)

Rate me:
Please Sign up or sign in to vote.
4.89/5 (11 votes)
4 Jun 2009LGPL35 min read 88.4K   6.3K   61  
Semi-automatic GUI generation from Domain Models.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Technewlogic.BusinessCore;
using Technewlogic.Stasy;
using Technewlogic.Samples.ManufacturingExecutionSystem.Backend.Context;
using Technewlogic.Crud;
using Technewlogic.BusinessCore.Validation.Exceptions;
using Technewlogic.BusinessCore.Validation;

namespace Technewlogic.Samples.ManufacturingExecutionSystem.Backend.DomainModel
{
	public partial class Order : BusinessObjectBase<Order>
	{
		public Order()
		{
			Lots = new CompositeCollection<Lot>();
			Lots.BeforeAdd += new EventHandler<EntityChangingEventArgs<Lot>>((s, e) =>
			{
				if (!e.Entity.Validate())
					throw new ValidationException(e.Entity.ValidationMessage);
			});

			_customerRef = new MasterRef<Customer>();
			_materialAggregation = new AggregateLink<Material>();

			AddRule(new ValidationRule(
				new ValidationException("Please fill in a name."),
				ValidateNameRequired));
			AddRule(new ValidationRule(
				new ValidationException("Please fill in a number."),
				ValidateNumberRequired));
			AddRule(new ValidationRule(
				new ValidationException("Please specify a material."),
				ValidateMaterialRequired));
			AddRule(new ValidationRule(
				new ValidationException("An order with this number already exists."),
				ValidateNumberUnique));
			AddRule(new ValidationRule(
				new ValidationException("The planned quantity has to be at least " + _minPlannedQuantity.ToString() + "."),
				ValidateQuantityRange));
		}

		private const double _minPlannedQuantity = 10.0;

		[BusinessContext]
		private ApplicationContext Context { get; set; }

		#region Data Properties

		[PrimaryKey]
		public Guid ID
		{
			get { return _id; }
		}

		[CrudPropertyConfiguration]
		public string Name
		{
			get { return _name; }
			set
			{
				_name = value;
				SendPropertyChanged("Name");
				Validate();
			}
		}

		[CrudPropertyConfiguration]
		public string Number
		{
			get { return _number; }
			set
			{
				_number = value;
				SendPropertyChanged("Number");
				Validate();
			}
		}

		[CrudPropertyConfiguration("Planned Quantity")]
		public double PlannedQuantity
		{
			get { return _plannedQuantity; }
			set
			{
				if (State != OrderState.Initial)
					throw new ValidationException("The planned quantity can only be changed in initial state.");

				// TODO: State überprüfen
				_plannedQuantity = value;
				SendPropertyChanged("PlannedQuantity");
				Validate();
			}
		}

		// Computed Value (TODO: Probleme mit Property Changed - an alle Lots anhängen)
		[CrudPropertyConfiguration("Actual Quantity",
			IsEnabledInEdit = false,
			IsEnabledInNew = false)]
		public double ActualQuantity
		{
			get { return Lots.Sum(it => it.Quantity); }
		}

		[CrudPropertyConfiguration]
		public OrderState State
		{
			get { return _state; }
			private set
			{
				_state = value;
				SendPropertyChanged("State");
				Validate();
			}
		}

		[ForeignKey(typeof(Customer))]
		private Guid CustomerID
		{
			get { return _customerID; }
			set { _customerID = value; }
		}
		private MasterRef<Customer> _customerRef;
		public Customer Customer
		{
			get { return _customerRef.Value; }
		}

		[ForeignKey(typeof(Material))]
		private Guid MaterialID
		{
			get { return _materialID; }
			set { _materialID = value; }
		}
		private AggregateLink<Material> _materialAggregation;
		[CrudPropertyConfiguration(
			IsEnabledInEdit = false,
			IsEnabledInNew = true)]
		public Material Material
		{
			get { return _materialAggregation.Value; }
			set
			{
				_materialAggregation.Value = value;
				SendPropertyChanged("Material");
				Validate();
			}
		}

		[CrudPropertyConfiguration(
			DisplayInGrid = false,
			DisplayInModification = false)]
		public CompositeCollection<Lot> Lots { get; set; }

		public override string Descriptor
		{
			get { return Name + " - " + Number; }
		}

		#endregion

		#region Operations

		public void Dispatch(Equipment equipment)
		{
			if (State != OrderState.Initial)
				throw new ValidationException("The order is already dispatched.");

			if (equipment == null)
				throw new ValidationException("Please specify an equipment.");

			if (Context.Lots.Any(it => it.Equipment == equipment))
				throw new ValidationException("The equipment " + equipment.Descriptor + " is in use.");

			State = OrderState.InProduction;

			var lot = Context.CreateInstance(() => new Lot());
			lot.Number = DateTime.Now.Ticks.ToString();
			lot.Equipment = equipment;
			lot.Quantity = 0.0;

			Lots.Add(lot);
		}

		public void Close(Equipment equipment)
		{
			if (State != OrderState.InProduction)
				throw new ValidationException("The order is not in production.");

			if (equipment == null)
				throw new ValidationException("Please specify an equipment.");

			State = OrderState.Closed;
			var lot = Context.CreateInstance(() => new Lot());
			lot.Number = DateTime.Now.Ticks.ToString();
			lot.Equipment = null;
			lot.Quantity = PlannedQuantity;

			Lots.Add(lot);
		}

		public void ShipToCustomer()
		{
			if (State != OrderState.Closed)
				throw new ValidationException("The order is not closed or has already been shipped.");

			State = OrderState.Shipped;
			var lot = Context.CreateInstance(() => new Lot());
			lot.Number = DateTime.Now.Ticks.ToString();
			lot.Equipment = null;
			lot.Quantity = PlannedQuantity;
			lot.IsCustomerLot = true;

			Lots.Add(lot);
		}

		#endregion

		#region Validation

		private bool ValidateNameRequired()
		{
			return ValidateStringNotEmpty(Name);
		}

		private bool ValidateNumberRequired()
		{
			return ValidateStringNotEmpty(Number);
		}

		private bool ValidateMaterialRequired()
		{
			return Material != null;
		}

		private bool ValidateNumberUnique()
		{
			return !Context.Orders
				.Where(it => it.ID != ID)
				.Where(it => it.Number == Number)
				.Any();
		}

		private bool ValidateQuantityRange()
		{
			return PlannedQuantity >= _minPlannedQuantity;
		}

		#endregion
	}
}

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, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) www.technewlogic.de
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions